【问题标题】:How to include/inject functions which use $scope into a controller in angularjs?如何将使用 $scope 的函数包含/注入到 angularjs 的控制器中?
【发布时间】:2013-11-07 15:48:32
【问题描述】:

我正在尝试将工厂中保存的函数库包含到控制器中。 类似于这样的问题: Creating common controller functions

我的主控制器如下所示:

recipeApp.controller('recipeController', function ($scope, groceryInterface, ...){

$scope.groceryList = [];
// ...etc...    

/* trying to retrieve the functions here */
$scope.groceryFunc = groceryInterface; // would call ng-click="groceryFunc.addToList()" in main view
    /* Also tried this:
    $scope.addToList = groceryInterface.addToList();
    $scope.clearList = groceryInterface.clearList();
    $scope.add = groceryInterface.add();
    $scope.addUp = groceryInterface.addUp(); */
}

然后,在另一个.js 文件中,我创建了工厂的groceryInterface。我已经将这个工厂注入到上面的控制器中。

工厂

recipeApp.factory('groceryInterface', function(){

        var factory = {};

    factory.addToList = function(recipe){
        $scope.groceryList.push(recipe);
                    ... etc....
    }

    factory.clearList = function() {
            var last = $scope.prevIngredients.pop();
            .... etc...
    }

    factory.add = function() {
    $scope.ingredientsList[0].amount = $scope.ingredientsList[0].amount + 5;
    }

    factory.addUp = function(){
        etc...
    }

    return factory;
});

但在我的控制台中,我不断收到ReferenceError: $scope is not defined at Object.factory.addToList 等。 显然我猜这与我在工厂内的函数中使用$scope 的事实有关。我该如何解决这个问题?我注意到在我看过的许多其他示例中,没有人在他们的外部工厂函数中使用$scope。我曾尝试在我的工厂中将$scope 作为参数注入,但这种方法并没有奏效。 (例如recipeApp.factory('groceryInterface', function(){

非常感谢任何帮助!

【问题讨论】:

    标签: javascript angularjs dependency-injection factory controllers


    【解决方案1】:

    你不能在工厂中使用$scope,因为它没有被定义。相反,在您的工厂函数中更改工厂返回的对象的属性,例如

    factory.addToList = function (recipe) {
        this.groceryList.push(recipe);
    }
    

    然后这些将传递给您的 $scope 变量

    $scope.addToList = groceryInterface.addToList;
    // ... = groceryInterface.addToList(); would assign to `$scope.addToList` what is returned, instead of the function itself. 
    

    【讨论】:

    • 谢谢,我试试看!
    • 我编辑了您的解决方案,而不是 $scope.addToList = groceryInterface.addToList();,而是改为 $scope.addToList = groceryInterface.addToList; 我发现 addTotList() 末尾的括号是我调试过程中的一个大问题......让我自己相当令人耳目一新的 javascript 语法...
    【解决方案2】:

    这不是这个问题的确切答案,但我有一个类似的问题,我通过简单地将 $scope 作为参数传递给我工厂中的函数来解决。所以它不会是正常的 $scope,而是调用工厂中的函数时的 $scope。

    app.controller('AppController', function($scope, AppService) {
    
    
      $scope.getList = function(){
    
        $scope.url = '/someurl'
    
        // call to service to make rest api call to get data
    
        AppService.getList($scope).then(function(res) {
          // do some stuff 
    
        });
      }
    
    });
    
    
    app.factory('AppService', function($http, $q){
      var AppService = {
    
        getList: function($scope){
          return $http.get($scope.url).then(function(res){
            return res;
          });
        },
    
      }
    
      return AppService;
    });
    

    【讨论】:

    • DRY AF.. 以及将参数传递给工厂函数的方法
    【解决方案3】:

    您的工厂无法访问您的$scope,因为它不在同一个范围内。

    试试这个:

    recipeApp.controller('recipeController', function ($scope, groceryInterface) {
    
        $scope.addToList = groceryInterface.addToList;
        $scope.clearList = groceryInterface.clearList;
        $scope.add       = groceryInterface.add;
        $scope.addUp     = groceryInterface.addUp;
    }
    
    recipeApp.factory('groceryInterface', function () {
    
        var factory = {};
    
        factory.addToList = function (recipe) {
            this.groceryList.push(recipe);
        }
    
        factory.clearList = function() {
            var last = this.prevIngredients.pop();
        }
    });
    

    或者,您可以尝试使用更面向对象的方法:

    recipeApp.controller('recipeController', function ($scope, groceryInterface) {
    
        $scope.groceryFunc = new groceryInterface($scope);
    }
    
    recipeApp.factory('groceryInterface', function () {
    
        function Factory ($scope) {
    
            this.$scope = $scope;
        }
    
        Factory.prototype.addToList = function (recipe) {
            this.$scope.groceryList.push(recipe);
        }
    
        Factory.prototype.clearList = function() {
            var last = this.$scope.prevIngredients.pop();
        }
    
        return Factory;
    });
    

    【讨论】:

    • @Gnuey - 请注意,bind 在旧版本的 IE 中不可用。如果您必须支持这些并希望使用第一种方法,请使用 this MDN polyfill,或者 - 如果页面上有 jQuery - 使用 $.proxy 代替。
    • 好的,太好了。这实际上是非常有用的信息——我的部门负责人和网站访问者有时出于某种原因使用旧版 IE:\ 我会改为写 $scope.addToList = $.proxy(groceryInterface.addToList, $scope) 吗?
    • @Gnuey - 是的。就是这样。
    • 嗯,我得到了TypeError: Cannot call method 'push' of undefined at Object.factory.addToList 我忘了提到groceryList 是主控制器中的一个数组($scope.groceryList = [])。这有什么不同吗?
    • @Gnuey - 你能创建一个short concise 解决你的问题吗?
    猜你喜欢
    • 1970-01-01
    • 2015-04-02
    • 1970-01-01
    • 1970-01-01
    • 2016-04-09
    • 1970-01-01
    • 2014-03-02
    • 2014-10-14
    • 1970-01-01
    相关资源
    最近更新 更多