AngularJS功能可用于多个控制器

时间:2014-09-22 21:00:41

标签: javascript angularjs

AngularJS + Rest API中构建一个简单的控制面板。

构建一个简单的工厂,生成API请求(GET, POST)并将必要的数据返回到成功回调。需要处理返回数据并更改$scope,因为API可以返回服务器端表单字段错误。

我无法在工厂内构建处理/更改$scope,因为工厂没有(并且不应该)访问范围。我不希望在成功回调中处理/应用,因为它会重复(每个API请求一次)。

什么是最好的" Angular方式"解决这个问题?

一种可能的解决方案是在Angular应用程序之外存在一个函数,然后只传递$​​ scope和必要的数据。

这感觉就像是一个糟糕的工作(见下文)。

myApp.controller("saveForm", ["$scope", "api", function($scope, api), function() {
    ...
    $scope.submit = function() {
        api("POST", url, $scope.data, function(data) {
            //onSuccess
            processData($scope, data);
        });
    }
    ...
}]);

myApp.factory('api', ['$http', function($http) {
    return function(method, url, input, success, error) {
        //Retrieve data from API. Note that factory DOES NOT have access to $scope.
        $http(...
    }
}]);

var processData = function(scope, data) {
    angular.forEach(data, function(value, key)) {
        scope....
    }
}

4 个答案:

答案 0 :(得分:1)

我不确定是否有你,但你可以以混合方式扩展控制器:

基本控制器

(function() {
  'use strict';

  angular.module('Base', []);

  function BaseController($scope, <injectables>, that) {
    that.mixin1 = function() {
    };

    that.mixin2 = function(arg1, arg2) {
    };
  }

  angular.module('Base').controller('BaseController',
    ['$scope', '...', BaseController]);
})();

继承控制器

(function() {
  'use strict';

  angular.module('Derived', ['Base']);

  function DerivedController($scope, $controller, ...) {
    $controller('BaseController', {
      '$scope' : $scope,
      ...
      'that' : this
    });

    // this.mixin1
    // this.mixin2
  }

  angular.module('Derived').controller('DerivedController',
    ['$scope', '$controller', '...', DerivedController]);
})();

请注意,您使用Angular的$controller服务来混合功能。

答案 1 :(得分:0)

为什么不在控制器中包含一个处理它的函数?这就是我通常处理它的方式:

myApp.controller("saveForm", ["$scope", "api", function($scope, api), function() {
    ...
    $scope.submit = function() {
        api("POST", url, $scope.data, function(data) {
            //onSuccess
            processData(data);
        });
    }
    function provessData(data){
        // do stuff to data
        $scope.foo = data;
    }
    ...
}]);

答案 2 :(得分:0)

看起来你的控制器做了太多工作并且对实际请求了解太多(网址,&#34; POST&#34;等等)。

如何将工厂中的数据转换为控制器所期望的内容。工厂不需要了解范围。它只是将数据转换为控制器可以使用的格式,然后将其发送回去。通过这种方式,工厂可以在控制器之间重复使用。

myApp.controller("saveForm", ["$scope", "api", function($scope, api), function() {
    ...
    $scope.submit = function() {

// Call API.update and handle the deferred that is returned, which will be the transformed data
        api.update($scope.data).then(function (transformedData) {
           scope....

        });
    }
    ...
}]);

myApp.factory('api', ['$http', '$q', function($http, $q) {
    return {
         update : function () {

             var deferred = $q.defer();

             $http({
               method: "GET",
               url: "your/url/path"

             }).success(function(data) {

                var transformedData;

                // Perform data transformation here instead of in controllers
                angular.forEach(data, function (value, key) {
                    transformedData.....
                });

                deferred.resolve(transformedData);
             });

             return deferred.promise;
         }
    }
}]);

答案 3 :(得分:0)

您可以创建一个返回processData函数的工厂:

myApp.factory('processData', [function () {
    return function(scope, data) {
        angular.forEach(data, function(value, key)) {
            scope....
        }
    };
}]);

然后用angular注入它:

myApp.controller("saveForm", ["$scope", "api", "processData", function($scope, api, processData) {
    ...
    $scope.submit = function() {
        api("POST", url, $scope.data, function(data) {
            //onSuccess
            processData($scope, data);
        });
    }
    ...
}]);

这种方法优于在DI之外声明的函数的优点是,如果需要,在单元测试中模拟processData依赖关系仍然很容易。