AngularJS - вызов функции контроллера из службы
Я так зеленый в Angular, я даже не уверен, что правильно структурировал поиск. Вся директива и терминология обслуживания все еще меня путают, но это не мой вопрос.
Я прочитал эту замечательную серию статей позади: http://www.ng-newsletter.com/posts/beginner2expert-how_to_start.html
Вот почему я сейчас нахожусь в своем приложении. И почему я знаю, что мой вопрос больше связан с взаимоотношениями между службами и контроллерами. Вместо синтаксиса.
Итак, вот обзор приложения:
У меня есть один контроллер. Это отключается и получает кучу данных фермы для пользователя, использующего вызов AJAX в PHP файл, и отображает его на экране, используя собственную область видимости.
var masterApp = angular.module('masterApp', ['myFilters','commonControls']);
masterApp.controller('MasterCtrl', ['$scope','$http', '$filter', 'commonFarmSelector',
function($scope, $http, $filter, commonFarmSelector){
...
$scope.masterCtrl.loadFarmData = function(farmId) {
var postdata = {
"farmId":farmId
};
$http.post('/service/farmproduction', postdata).success(function (data) {
// Do stuff with the $scope using data
}
}
$scope.masterCtrl.loadFarms();
}
Вы увидите, что я впрыскиваю что-то под названием commonControls. Это был модуль, который я создал для хранения элементов управления, которые будут повторно использоваться несколькими контроллерами. В этом случае выпадающее поле, содержащее список ферм, к которым пользователь имеет доступ (также полученный по вызову AJAX):
var commonControlsApp = angular.module('commonControls', []);
commonControlsApp.controller('farmSelectorCtrl', ['$scope', '$http',function($scope, $http) {
$scope.farmSelectorCtrl ={}
// Change entire farm view when a different farm is selected
$scope.farmSelectorCtrl.switchUserFarm = function() {
var farmId = $scope.farmSelectorCtrl.selectedUserFarm;
$scope.masterCtrl.loadFarms(farmId); // !!! Direct link to masterCtrl
};
// Get a list of the user farms
$http.post('/service/userfarms').success(function (data) {
$scope.farmSelectorCtrl.userFarms = data.getFarmsPerUserResult.farmIds;
});
}]);
Это прекрасно работает. Но, как вы можете видеть, farmSelector напрямую связан с masterCtrl. И поведение этой функции loadFarmData специфично для этого контроллера. Другими словами, он будет делать только то, что относится к этой странице.
Дело в том, что этот farmSelector будет использоваться на других страницах. И точное поведение события изменения будет отличаться для каждой страницы. Поэтому я изо всех сил пытаюсь разобраться, где должно сидеть такое поведение. И как он будет называться зависимым от контроллера с помощью farmSelector.
В статье, которая была приведена выше, предлагается, что этот фермерский выбор должен быть в службе, чтобы его можно было повторно использовать в другом месте. Но я все еще смущен тем, как вы могли бы дать универсальную услугу определенное действие, которое нужно предпринять, когда срабатывает событие.
Ответы
Ответ 1
Я очень рекомендую услугу, по той же причине, о которой предлагает статья. Он также имеет отличный ответ на вашу проблему.
Технический термин для того, что вы хотите, это функция calback. Это конкретное действие, которое необходимо предпринять, когда событие инициируется, а раздел "Службы" статьи является хорошим примером того, как это сделать.
Взгляните на этот раздел статьи "Услуги" (который я урезал до важных частей)
angular.module('myApp.services', [])
.factory('githubService', ['$http', function($http) {
var doRequest = function(username) {
return $http({
url: 'https://MySuperURL.com/getTheData'
});
}
return {
events: doRequest
};
}]);
Итак, теперь у нас есть услуга, называемая githubService
, которая имеет один метод: events
(это действительно просто другое имя для doRequest
; я сохранил переименование так, чтобы оно соответствовало статье код).
Скрытым здесь за кулисами является API $q
, который иногда называют API-интерфейсом "обещание" . Функция $http
возвращает объект "обещание" , что на самом деле является способом для кода отслеживать, что должно произойти, когда "обещание" будет выполнено. Например, рассмотрим следующий код (опять же, измененный в версии статьи):
app.controller('ServiceController', ['$scope', 'githubService',
function($scope, githubService) {
// uses the $http service to call the GitHub API
// and returns the resulting promise
githubService.events(newUsername)
.success(function(data, status, headers) {
// do magic stuff with the result
// (which is in the data param)
$scope.events = data.data;
})
});
}]);
Здесь происходит "волшебство". Посмотрите на вызов success()
, и вы увидите, что они фактически передают function
, который должен запускаться, когда запрос работает. Функция все еще имеет доступ ко всем переменным в ServiceController
из-за закрытия, поэтому разрешено использовать $scope
и другие переменные. Тем не менее, очень легко написать другой метод success()
в каждом контроллере, каждый раз передавая разные функции, что позволяет нескольким контроллерам выполнять разные действия. Когда запрос завершится, он вызовет каждую функцию success
, которую он дал.
Вы можете выполнить этот пример кода и получить рабочую модель, но я также предлагаю вам взглянуть на $q в angular, а также взгляните на эту статью о функции обратного вызова. Вам нужно понять, как реально получить то, что происходит, но хорошей новостью является то, что они оба используются довольно часто в angular, поэтому он будет стоить вашего времени.