Angularjs 未知提供程序:$controller
我可以访问$controllerProvider,但无法使用以下方法访问$controllerAngularjs 未知提供程序:$controller,angularjs,Angularjs,我可以访问$controllerProvider,但无法使用以下方法访问$controller angular.module(MODULE_NAME, ['common']) .config(['$routeProvider','$controllerProvider', function($routeProvider, $controllerProvider) { console.log($controllerProvider);//defined
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';
}
上下文
我正在创建一个项目的架构。我的项目结构如下
我不想创建一个继承公共ListController但不做任何额外更改的MODXListController。因为我有很多模块,将近25个,而且大部分都共享相同的功能。在.config中,您只能使用提供程序(例如$routeProvider) 在.run中,您只能使用服务实例(例如$route) $controller属于服务类型,无法在.config中使用 欲了解更多有关此的详细信息,请阅读
关于线程堆栈溢出的详细讨论显示了可以注入到其他线程中的内容。您不能将
$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)
函数来检查您的控制器是否已定义。而无需显式继承所有控制器(这是可接受但详细的解决方案),一个好的替代方法是将控制器切换功能包装到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),因此服务提供程序也可以与服务实例相同的方式在配置
块中声明路由控制器:
...
controller: ctrlFactoryProvider.get('ListController')
由于
$controller
不公开已注册控制器的列表,请尝试将其作为自动解决方案,这是人们最不愿意做的事情:除此之外,它是一种黑客攻击,它只会抑制可能的异常并破坏可测性。如果我使用$controller作为依赖项注入,这是给未知的提供者:$controllerI在发布这个问题之前已经看到了那个帖子。我也无法访问该服务,因此我尝试直接访问$controller。同样,我也无法访问ControllerChecker服务。:)不要在配置中注入此服务。相反,将其注入根控制器。然后是否可以检查控制器是否存在于.config中?请查看此线程已检查该帖子以及问题中的状态。有一个答案(由@trekforever发布)建议更新角度代码。有没有更好的方法?您无法从配置中访问$controller
。请提供上下文,说明为什么控制器存在时未知。有更好的方法来做你想做的事情,当然不是这样。@estus我已经更新了上下文。从抽象父级进行零更改扩展是OOP中的常见做法,不应该避免。特别是当替代方案不可行时(试试catch$controller很可怕,但其他的更糟糕)。有很多关于角度控制器继承的好方法。我喜欢这种方法。我一定会试试这个,让你知道。谢谢你宝贵的时间。还有一件事。我也在使用带有ng视图的ng路由器。这种做法是否会与之相适应。我的url pattarn类似于列表控制器的/list或编辑控制器的/edit/:id。原始问题中没有提到它,它是一个重要的细节,因为它改变了一切。请参阅更新。