如何检查是否已定义angularjs控制器

时间:2013-11-01 20:06:55

标签: angularjs config controllers

我有一个以这种方式定义的应用程序:

angular.module("myApp", [...])
  .config(function ($stateProvider, $controllerProvider) {
    if (isControllerDefined(controllerName)) {
      do_stuff();
    }
  })

控制器以这种方式定义:

angular.module("myApp")
  .controller("myController", function ($scope) { ... });

如果我拥有控制器的名称,如何定义isControllerDefined()(在上面的配置中)来检查给定的控制器是否存在?我觉得我应该做一些像这样的事情:

var ctrl = angular.module("myApp").getController("myController");
var ctrl = $controllerProvider.get("myController");

或类似的东西......但我找不到任何功能。帮助

5 个答案:

答案 0 :(得分:9)

可以检查控制器是否存在的服务示例。请注意,它会查找具有指定名称的global function以及$controller提供程序中的控制器。

angular.service('ControllerChecker', ['$controller', function($controller) {
  return {
    exists: function(controllerName) {
      if(typeof window[controllerName] == 'function') {
        return true;
      }
      try {
        $controller(controllerName);
        return true;
      } catch (error) {
        return !(error instanceof TypeError);
      }
    }
  };
}]);

有关用法,请参阅the fiddle

答案 1 :(得分:6)

前几天我遇到了同样的问题。我在当前接受的答案中遇到了一些问题,即因为我的一个控制器在实例化时正在执行初始化调用以填充一些数据(即):

function ExampleController($scope, ExampleService) {
    ExampleService.getData().then(function(data) {
        $scope.foo = data.foo;
        $scope.bar = data.bar
    });
}

目前,当前接受的答案实际上会在丢弃控制器之前实例化控制器。这导致在每个请求上进行多次API调用(一个用于验证控制器是否存在,一个用于实际使用控制器)。

我在$controller source code中进行了一些挖掘,发现你可以传入一个名为later的未记录参数,这会延迟实例化。但是,它仍将运行所有检查以确保控制器存在,这是完美的!

angular.factory("util", [ "$controller", function($controller) {
    return {
        controllerExists: function(name) {
            try {
                // inject '$scope' as a dummy local variable
                // and flag the $controller with 'later' to delay instantiation
                $controller(name, { "$scope": {} }, true);
                return true;
            }
            catch(ex) {
                return false;
            }
        }
    };
}]);

更新:作为装饰者可能要容易得多:

angular.config(['$provide', function($provide) {
    $provide.delegate('$controller', [ '$delegate', function($delegate) {
        $delegate.exists = function(controllerName) {
            try {
                // inject '$scope' as a dummy local variable
                // and flag the $controller with 'later' to delay instantiation
                $delegate(controllerName, { '$scope': {} }, true);
                return true;
            }
            catch(ex) {
                return false;
            }
        };

        return $delegate;
    }]);
}]);

然后您只需注入$controller并致电exists(...)

function($controller) {
    console.log($controller.exists('TestController') ? 'Exists' : 'Does not exist');
}

答案 2 :(得分:3)

目前还没有简单的方法来获取控制器列表。这仅供内部使用隐藏。你必须转到源代码并添加一个返回内部控制器变量的公共方法(在$ ControllerProvider函数中) https://github.com/angular/angular.js/blob/master/src/ng/controller.js#L16

this.getControllers = function() {
    return controllers;
    // This will return an object of all the currently defined controllers
  };

然后你可以做

app.config(function($controllerProvider) {
    var myCtrl = $controllerProvider.getControllers()['myController'];
});

答案 3 :(得分:3)

由于angular 1.5.1 (在编写时尚未发布),因此有一种新的方法可以通过$ControllerProvider.has('MyCtrlName')方法检查控制器是否存在。

Github问题:https://github.com/angular/angular.js/issues/13951

Github PR:https://github.com/angular/angular.js/pull/14109

直接在1.5.1中提交反向移植:https://github.com/angular/angular.js/commit/bb9575dbd3428176216355df7b2933d2a72783cd

免责声明:由于很多人都对这个功能感兴趣,我做了一个PR,因为我还需要它是我的一些项目。玩得开心! :)

这个PR基于@trekforever的回答,感谢提示:)

答案 4 :(得分:2)

您可以使用$ controller服务并执行$ controller('myController')并将try-catch包围,以便您知道它是否失败。