【问题标题】:Unknown provider: $controller未知提供者:$controller
【发布时间】:2015-11-20 09:48:49
【问题描述】:

我可以访问$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';
}

上下文

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

  1. 我有一个 COMMON 模块。使用 ListController、EditController、ViewController
  2. 我还有一些其他模块,如 MOD1、MOD2 等,带有 MOD1ListController、MOD1EditController、MOD1ViewController 等。
  3. 那些特定于模块的控制器从通用模块扩展相应的控制器。

现在我的计划是在需要开发一个新模块(MODX)的同时,如果有一些额外的功能,那么只有开发人员会通过继承通用的 ListController 为该模块创建一个新的 MODXListController。否则他们不需要创造任何东西。

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

我不想创建一个 MODXListController 继承公共 ListController 但不做任何额外的改变。因为我有很多模块,将近 25 个,而且大部分都共享相同的功能。

【问题讨论】:

  • 你不能从你的配置访问$controller
  • 请提供上下文,为什么控制器是否存在是未知的。有更好的方法来做你想做的事,当然不是那样的。
  • @estus 我已经更新了上下文。
  • 从抽象父级扩展零更改是 OOP 中的常见做法,不应避免。特别是如果替代方案不可行(try-catch $controller 很糟糕,但其他方案更糟)。 Angular 控制器继承有很多很好的方法。

标签: angularjs


【解决方案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),所以服务提供者也可以像服务实例一样在@987654327中声明路由控制器@块:

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

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

【讨论】:

  • 我喜欢这种方法。我一定会试试这个,让你知道。感谢您宝贵的时间。
  • 还有一件事。我也在使用带有 ng-view 的 ng-router。这种方法是否会与之相适应。我的 url pattarn 类似于 /list 用于列表控制器或 /edit/:id 用于编辑控制器。
  • 原始问题中没有提到它,这是一个重要的细节,因为它改变了一切。查看更新。
【解决方案2】:

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

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

$controller 属于服务类型,不能在 .config 中使用。

更多详情请阅读here.

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

【讨论】:

  • 那么是否可以检查.config中是否存在控制器?
  • 已经检查过该帖子以及问题中的提及。有一个答案(由@trekforever 发布)建议更新角度代码。有没有更好的办法?
【解决方案3】:

您不能将$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) 函数来检查您的控制器是否已定义。

【讨论】:

  • 如果我使用 $controller 作为依赖注入,它会给 Unknown provider: $controller
  • 在发布这个问题之前我已经看过那个帖子了。我也无法访问该服务,所以我尝试直接访问 $controller。
  • 同样我也无法访问 ControllerChecker 服务。 :)
  • 不要在配置中注入这个服务。而是将其注入您的根控制器中。
猜你喜欢
  • 1970-01-01
  • 2013-09-27
  • 2016-11-29
  • 2018-09-28
  • 2014-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多