未知提供商:$ controller

时间:2015-11-20 09:48:50

标签: angularjs

我可以访问$ controllerProvider,但无法通过以下方法访问$ controller

angular.module(MODULE_NAME, ['common'])
    .config(['$routeProvider','$controllerProvider',
      function($routeProvider, $controllerProvider) {
        console.log($controllerProvider);//defined
        console.log($controller);//undefined
}]);

如果我使用$ controller作为依赖注入,它就是

Unknown provider: $controller

但我需要访问它,我该怎么做

修改

我需要这个,因为我想检查我的控制器是否存在。以下是post我使用此代码的地方

try {
     $controller(controllerName);
     listControlerName = MODULE_NAME+'ListController';
} catch (error) {
     listControlerName = 'CommonListController';
}

CONTEXT

我正在创建项目的架构。我的项目结构如下。

  1. 我有一个COMMON模块。使用ListController,EditController,ViewController
  2. 我还有一些其他模块,如MOD1,MOD2等,MOD1ListController,MOD1EditController,MOD1ViewController等。
  3. 这些模块特定控制器从公共模块扩展相应的控制器。
  4. 现在我的计划是需要开发一个新模块(MODX),然后如果有一些额外的功能,那么只有开发人员将通过继承公共ListController为该模块创建一个新的MODXListController。否则他们不需要创造任何东西。

    因此系统将检查该模块是否包含MODXListController。如果没有,那么系统将使用Common ListController。

    我不想创建一个继承常见ListController但不做任何额外更改的MODXListController。因为我有大约25个模块,所有这些模块大部分都是共享相同的功能。

3 个答案:

答案 0 :(得分:1)

没有显式继承所有控制器(这是可接受的但是详细的解决方案),一个很好的选择是将控制器切换功能包装到mod-controller指令(类似于ng-controller),类似于:

angular.module('common', [])
.constant('MODULE_NAME', 'Common')
.constant('modControllers', [])
.controller('CommonEditController', ...);
.controller('CommonListController', ...);
.directive('modController', function (MODULE_NAME, modControllers) {
  return {
    restrict: 'A',
    scope: true,
    priority: 500,
    controller: function ($controller, $attrs, $scope) {
      var ctrlName = (modControllers.indexOf($attrs.modController) >=0 ? MODULE_NAME : 'Common') + $attrs.modController;

      angular.extend(this, $controller(ctrlName, { $scope: $scope }));
    });
  };
});

angular.module('mod1', ['common'])
.constant('MODULE_NAME', 'Mod1')
.constant('modControllers', ['ListController']);
.controller('Mod1ListController', function ($controller) {
  angular.extend(this, $controller('CommonListController');
  ...
});

当应在应用程序代码而不是视图(即路由和指令控制器)中指定控制器时,可以使用控制器工厂完成类似的操作。

angular.module('common')
.provider('ctrlFactory', function (MODULE_NAME, modControllers) {
  function factoryFn(ctrlName) {
    return (modControllers.indexOf(ctrlName) >=0 ? MODULE_NAME : 'Common') + ctrlName;
  };

  this.get = this.$get = factoryFn;
});

它可以注入指令并用作

...
controller: ctrlFactory('ListController')

由于它返回控制器名称而不是$controller实例并且仅依赖于常量服务(MODULE_NAME,modControllers),因此服务提供者也可以像服务实例一样使用来声明路由控制器config阻止:

...
controller: ctrlFactoryProvider.get('ListController')

因为$controller没有公开已注册的控制器列表,所以尝试捕获它作为自动解决方案,这是人们可能想要做的最后一件事:除了它是一个黑客,它只是抑制可能的例外并损害可测试性。

答案 1 :(得分:0)

在.config中,您只能使用提供程序(例如$ routeProvider)。

在.run中,您只能使用服务实例(例如$ route)。

  

$ controller属于service类型,无法在.config中使用。

有关此阅读here.

的详细信息

this线程上有关Stack Overflow的详细讨论显示了可以注入其他内容的内容。

答案 2 :(得分:0)

您无法将$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);
      }
    }
  };
}]);

现在您可以注入ControllerChecker并调用其exists(CtrlName)函数来检查您的控制器是否已定义。