未知的提供者:$controller

3
我可以访问 $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

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

编辑

我需要这个是因为我想检查我的控制器是否存在。这是我使用该代码的帖子

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。如果没有,则系统将使用通用的ListController。

我不想创建一个继承通用ListController但没有做任何额外改动的MODXListController。因为我有很多模块,近25个,它们大多数共享同样的功能。


你不能从配置中访问$controller - Abhilash Augustine
请提供具体的上下文说明为什么不确定控制器是否存在。肯定有更好的方法来实现你想做的事情,而不是像那样做。 - Estus Flask
@estus 我已经更新了上下文。 - Partha Sarathi Ghosh
1
在OOP中,从抽象父类扩展而不做任何更改是常见的实践,不应该避免。特别是如果其他选择不可行(try-catch $controller非常糟糕,但其他选择更糟)。有许多很好的Angular控制器继承的示例。 - Estus Flask
3个回答

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没有公开注册控制器的列表,所以想到了使用try-catch来解决问题,但这是一个自动化的解决方案,也是最后一个人想做的事情:除了它是一个hack之外,它只是压制可能的异常并破坏了可测试性。


我喜欢这种方法。我一定会尝试并告诉你。感谢您宝贵的时间。 - Partha Sarathi Ghosh
还有一件事。我也正在使用ng-router和ng-view。这种方法适用于它吗?我的URL模式类似于/list用于列表控制器或/edit/:id用于编辑控制器。 - Partha Sarathi Ghosh
1
原问题中没有提到这一点,但它是一个重要的细节,因为它改变了一切。请查看更新。 - Estus Flask

0

你不能将$controller注入 config 中。

虽然你可以使用以下服务来检查你的控制器是否已定义。

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作为依赖注入,它会报错:未知的提供者:$controller。 - Partha Sarathi Ghosh
在发布这个问题之前,我已经看过那篇帖子了。我也无法访问那个服务,所以我尝试直接访问$controller。 - Partha Sarathi Ghosh
我也无法访问ControllerChecker服务。 :) - Partha Sarathi Ghosh
不要将此服务注入到配置中。相反,应该将其注入到您的根控制器中。 - Vivek

0
在 .config 中,您只能使用提供程序(例如 $routeProvider)。
在 .run 中,您只能使用服务实例(例如 $route)。 $controller 是一种服务类型,不能在 .config 中使用。
有关详细信息,请阅读此处
Stack Overflow 上的详细讨论线程显示了可以注入其他内容。

在.config中检查控制器是否存在,这是否可能? - Partha Sarathi Ghosh
请查看此线程 https://dev59.com/43jZa4cB1Zd3GeqPgqqG - J-D
已经查看了该帖子并在问题中提到。有一个答案(由@trekforever发布),建议更新Angular代码。是否有更好的方法? - Partha Sarathi Ghosh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接