Короткий ответ НЕТ, у нас на этом этапе в CSS нет parent selector
, но если вы все равно не хотите менять элементы или классы, второй вариант использует JavaScript, что-то вроде этого:
var activeATag = Array.prototype.slice.call(document.querySelectorAll('a.active'));
activeATag.map(function(x) {
if(x.parentNode.tagName === 'LI') {
x.parentNode.style.color = 'red'; //your property: value;
}
});
или более короткий путь, если вы используете jQuery в своем приложении:
$('a.active').parents('li').css('color', 'red'); //your property: value;
$scope
, который вы видите впрыснутым в контроллеры, - это не какая-то услуга (например, остальная часть инъектируемого материала), а объект Scope. Многие объекты области могут быть созданы (обычно прототипно наследуется от родительской области). Корнем всех областей является $rootScope
, и вы можете создать новую область с помощью метода $new()
любой области (включая $rootScope
).
Целью области является «склеить» презентацию и бизнес-логику вашего приложения. Не имеет смысла передавать $scope
в службу.
Службы - это одноэлементные объекты, используемые (среди прочего) для обмена данными (например, среди нескольких контроллеров) и, как правило, инкапсулировать многократно используемые фрагменты кода ( поскольку они могут быть введены и предлагать свои «услуги» в любой части вашего приложения, которая им нужна: контроллеры, директивы, фильтры, другие сервисы и т. д.).
Я уверен, что для вас будут работать различные подходы. Один из них таков: поскольку StudentService
отвечает за работу со студенческими данными, вы можете иметь StudentService
держать массив учеников и позволить ему «делиться» с кем-то, кто может быть заинтересован (например, ваш $scope
). Это имеет еще больший смысл, если есть другие представления / контроллеры / фильтры / службы, которые должны иметь доступ к этой информации (если нет сейчас, не удивляйтесь, если они скоро появятся). Каждый раз, когда добавляется новый ученик (с использованием метода save()
службы], собственный массив учеников будет обновляться, и каждый другой объект, совместно использующий этот массив, будет автоматически обновляться.
Основываясь на описанный выше, ваш код может выглядеть следующим образом:
angular.module('cfd', [])
.factory('StudentService', ['$http', function ($http) {
var path = 'data/people/students.json';
var students = [];
/* In the real app, instead of just updating the students array
* (which will be probably already done from the controller)
* this method should send the student data to the server */
var save = function (student) {
if (student.id === null) {
students.push(student);
} else {
for (var i = 0; i < students.length; i++) {
if (students[i].id === student.id) {
students[i] = student;
break;
}
}
}
};
/* Populate the students array with students from the server */
$http.get(path).success(function (data) {
data.forEach(function (student) {
students.push(student);
});
});
return {
students: students,
save: save
};
}])
.controller('someCtrl', ['$scope', 'StudentService',
function ($scope, StudentService) {
$scope.students = StudentService.students;
$scope.saveStudent = function (student) {
// Do some $scope-specific stuff
// Do the actual saving using the StudentService
StudentService.save(student);
// The $scope's `students` array will be automatically updated
// since it references the StudentService's `students` array
// Do some more $scope-specific stuff,
// e.g. show a notification
};
}
]);
. При использовании этого подхода вы должны быть осторожны, чтобы никогда не переписывать службы массив, потому что тогда любые другие компоненты (например, области) будут по-прежнему ссылаться на исходный массив, и ваше приложение сломается. Например. чтобы очистить массив в
StudentService
:
/* DON'T DO THAT */
var clear = function () { students = []; }
/* DO THIS INSTEAD */
var clear = function () { students.splice(0, students.length); }
См. также эту короткую демонстрацию .
LITTLE UPDATE:
Несколько слов, чтобы избежать путаницы, которая может возникнуть при разговоре об использовании службы, но не создавая ее с помощью функции service()
.
Цитирование документов на $provide
:
Угловая служба - это одноэлементный объект, созданный фабрикой услуг. Эти сервисные заводы - это функции, которые, в свою очередь, создаются поставщиком услуг. Поставщики услуг - это функции конструктора. При создании экземпляра они должны содержать свойство, называемое
$get
, которое содержит функцию фабрики услуг. [...] ... служба$provide
имеет дополнительные вспомогательные методы для регистрации служб без указания поставщика:blockquote>
- поставщик (поставщик) - регистрирует поставщика услуг с помощью $ injector
- constant (obj) - регистрирует значение / объект, к которому могут обращаться провайдеры и службы.
Значение- (obj) - регистрирует значение / объект, к которому могут обращаться только службы, а не провайдеры.
- factory (fn) - регистрирует функцию фабрики услуг fn, которая будет обернута в объект поставщика услуг, свойство $ get будет содержать заданную заводскую функцию.
- service (класс) - регистрирует функцию-конструктор, класс, который будет обернут в объект поставщика услуг, свойство $ get будет создавать экземпляр нового объекта с использованием данной функции конструктора.
В основном, то, что он говорит, заключается в том, что каждая функция Angular регистрируется с помощью
$provide.provider()
, но для более простых сервисов существуют «короткие» методы (две из которых -service()
иfactory()
). Все это «сводится» к сервису, поэтому не имеет большого значения, какой метод вы используете (до тех пор, пока требования к вашему сервису могут быть покрыты этим методом).BTW,
provider
vsservice
vsfactory
- одна из самых запутанных концепций для угловых новичков, но, к счастью, есть много ресурсов (здесь на SO), чтобы облегчить ситуацию. (Просто найдите вокруг.)(надеюсь, что это очистит - дайте мне знать, если это не так.)
Вы можете полностью отключить свой сервис от области видимости, но в вашем контроллере можно обновить область асинхронно.
Проблема, с которой вы сталкиваетесь, заключается в том, что вы не знаете, что HTTP-вызовы выполняются асинхронно, а это значит, что вы не получаете значение сразу, как вы могли. Например,
var students = $http.get(path).then(function (resp) {
return resp.data;
}); // then() returns a promise object, not resp.data
Существует простой способ обойти это, и он должен обеспечить функцию обратного вызова.
.service('StudentService', [ '$http',
function ($http) {
// get some data via the $http
var path = '/students';
//save method create a new student if not already exists
//else update the existing object
this.save = function (student, doneCallback) {
$http.post(
path,
{
params: {
student: student
}
}
)
.then(function (resp) {
doneCallback(resp.data); // when the async http call is done, execute the callback
});
}
.controller('StudentSaveController', ['$scope', 'StudentService', function ($scope, StudentService) {
$scope.saveUser = function (user) {
StudentService.save(user, function (data) {
$scope.message = data; // I'm assuming data is a string error returned from your REST API
})
}
}]);
Форма:
<div class="form-message">{{message}}</div>
<div ng-controller="StudentSaveController">
<form novalidate class="simple-form">
Name: <input type="text" ng-model="user.name" /><br />
E-mail: <input type="email" ng-model="user.email" /><br />
Gender: <input type="radio" ng-model="user.gender" value="male" />male
<input type="radio" ng-model="user.gender" value="female" />female<br />
<input type="button" ng-click="reset()" value="Reset" />
<input type="submit" ng-click="saveUser(user)" value="Save" />
</form>
</div>
Это позволило сократить часть вашей бизнес-логики для краткости, и я на самом деле не протестировал код, но что-то вроде этого будет работать. Основной концепцией является передача обратного вызова от контроллера к службе, которая будет вызвана позже в будущем. Если вы знакомы с NodeJS, это та же концепция.
Службы - это синглтоны, и не логично вводить область в службу (что действительно так, вы не можете вводить область в службу). Вы можете передать область как параметр, но это также плохой выбор дизайна, потому что у вас будет область, редактируемая в нескольких местах, что затрудняет ее отладку. Код для обработки переменных области должен идти в контроллере, а служебные вызовы идут на службу.
Хорошо (длинный) ... если вы настаиваете на , чтобы иметь доступ к $scope
внутри службы, вы можете:
ngapp.factory('Scopes', function (){
var mem = {};
return {
store: function (key, value) { mem[key] = value; },
get: function (key) { return mem[key]; }
};
});
ngapp.controller('myCtrl', ['$scope', 'Scopes', function($scope, Scopes) {
Scopes.store('myCtrl', $scope);
}]);
ngapp.factory('getRoute', ['Scopes', '$http', function(Scopes, $http){
// there you are
var $scope = Scopes.get('myCtrl');
}]);
Вместо того, чтобы пытаться изменить $scope
внутри службы, вы можете реализовать $watch
в своем контроллере, чтобы просмотреть свойство в своей службе для изменений, а затем обновить свойство на $scope
. Вот пример, который вы можете попробовать в контроллере:
angular.module('cfd')
.controller('MyController', ['$scope', 'StudentService', function ($scope, StudentService) {
$scope.students = null;
(function () {
$scope.$watch(function () {
return StudentService.students;
}, function (newVal, oldVal) {
if ( newValue !== oldValue ) {
$scope.students = newVal;
}
});
}());
}]);
Следует отметить, что в вашей службе, чтобы свойство students
было видимым, оно должно быть на службе объект или this
следующим образом:
this.students = $http.get(path).then(function (resp) {
return resp.data;
});
Попал в такое же затруднительное положение. Я закончил со следующим. Таким образом, здесь я не вводя объект области в фабрику, но устанавливая $ scope в самом контроллере, используя концепцию обещания, возвращаемую сервисом $ http.
(function () {
getDataFactory = function ($http)
{
return {
callWebApi: function (reqData)
{
var dataTemp = {
Page: 1, Take: 10,
PropName: 'Id', SortOrder: 'Asc'
};
return $http({
method: 'GET',
url: '/api/PatientCategoryApi/PatCat',
params: dataTemp, // Parameters to pass to external service
headers: { 'Content-Type': 'application/Json' }
})
}
}
}
patientCategoryController = function ($scope, getDataFactory) {
alert('Hare');
var promise = getDataFactory.callWebApi('someDataToPass');
promise.then(
function successCallback(response) {
alert(JSON.stringify(response.data));
// Set this response data to scope to use it in UI
$scope.gridOptions.data = response.data.Collection;
}, function errorCallback(response) {
alert('Some problem while fetching data!!');
});
}
patientCategoryController.$inject = ['$scope', 'getDataFactory'];
getDataFactory.$inject = ['$http'];
angular.module('demoApp', []);
angular.module('demoApp').controller('patientCategoryController', patientCategoryController);
angular.module('demoApp').factory('getDataFactory', getDataFactory);
}());
service
илиfactory
- вы закончите с и Угловой сервис . Просто убедитесь, что вы понимаете , как работают каждый, и если это соответствует вашим потребностям. – gkalpak 15 April 2014 в 08:19