AngularJS - 从服务调用控制器功能

时间:2013-12-16 21:13:44

标签: angularjs angularjs-scope

我对Angular非常环保,我甚至不确定我是否正在构建一个正确的搜索。整个指令和服务术语仍然让我感到困惑,但这不是我的问题。

我从前到后阅读过这篇优秀的文章系列:http://www.ng-newsletter.com/posts/beginner2expert-how_to_start.html

这就是我申请时的原因。为什么我知道我的问题更多地涉及服务和控制器之间的关系。而不是语法相关。

所以这里是应用程序的概述:

我有一个控制器。这样就可以使用对PHP文件的AJAX调用为用户获取大量的场数据,并使用它自己的$ scope在屏幕上显示它。

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's farms
    $http.post('/service/userfarms').success(function (data) {
        $scope.farmSelectorCtrl.userFarms = data.getFarmsPerUserResult.farmIds;
    });

}]);

这很好用。但正如您所看到的,farmSelector直接链接到masterCtrl。并且该loadFarmData函数的行为特定于该控制器。换句话说,它只会执行适用于该页面的内容。

问题是,这个farmSelector将用于其他页面。并且每个页面的更改事件的精确行为将是不同的。所以我正在努力找出这种行为应该存在的地方。以及如何使用farmSelector调用它依赖于控制器。

我上面链接的文章表明这​​个farmSelector应该在服务中,因此可以在其他地方重用。但我仍然对如何在触发事件时为通用服务提供特定操作感到困惑。

1 个答案:

答案 0 :(得分:11)

我强烈推荐一项服务,原因与文章建议的相同。它也可以很好地解决您的问题。

您想要的技术术语是 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的另一个名称;我保留了重命名,以便它会与文章的代码相匹配。)

隐藏在幕后的是 $q API,有时也称为“承诺”API。函数$http返回一个'promise'对象,这实际上只是代码跟踪'promise'完成时应该发生什么的一种方式。例如,让我们看看下一个代码(再次,从文章的版本中修改):

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 in angular,并查看有关callback functions的文章。你需要了解两者才能真正得到正在发生的事情,但好消息是它们经常以角度使用,所以值得你花时间。