问题描述
我是 Angular 的新手,并试图弄清楚如何做事......
I'm new to Angular and trying to figure out how to do things...
使用 AngularJS,如何注入要在另一个控制器中使用的控制器?
Using AngularJS, how can I inject a controller to be used within another controller?
我有以下片段:
var app = angular.module("testApp", ['']);
app.controller('TestCtrl1', ['$scope', function ($scope) {
$scope.myMethod = function () {
console.log("TestCtrl1 - myMethod");
}
}]);
app.controller('TestCtrl2', ['$scope', 'TestCtrl1', function ($scope, TestCtrl1) {
TestCtrl1.myMethod();
}]);
当我执行这个时,我收到错误:
When I execute this, I get the error:
Error: [$injector:unpr] Unknown provider: TestCtrl1Provider <- TestCtrl1
http://errors.angularjs.org/1.2.21/$injector/unpr?p0=TestCtrl1Provider%20%3C-%20TestCtrl1
我是否应该尝试在另一个控制器内部使用控制器,还是应该将其设为服务?
Should I even be trying to use a controller inside of another controller, or should I make this a service?
推荐答案
如果您的目的是获取另一个组件的已经实例化的控制器,并且如果您遵循基于组件/指令的方法,您总是可以require
来自遵循特定层次结构的另一个组件的控制器(组件的实例).
If your intention is to get hold of already instantiated controller of another component and that if you are following component/directive based approach you can always require
a controller (instance of a component) from a another component that follows a certain hierarchy.
例如:
//some container component that provides a wizard and transcludes the page components displayed in a wizard
myModule.component('wizardContainer', {
...,
controller : function WizardController() {
this.disableNext = function() {
//disable next step... some implementation to disable the next button hosted by the wizard
}
},
...
});
//some child component
myModule.component('onboardingStep', {
...,
controller : function OnboadingStepController(){
this.$onInit = function() {
//.... you can access this.container.disableNext() function
}
this.onChange = function(val) {
//..say some value has been changed and it is not valid i do not want wizard to enable next button so i call container's disable method i.e
if(notIsValid(val)){
this.container.disableNext();
}
}
},
...,
require : {
container: '^^wizardContainer' //Require a wizard component's controller which exist in its parent hierarchy.
},
...
});
现在上面这些组件的用法可能是这样的:
Now the usage of these above components might be something like this:
<wizard-container ....>
<!--some stuff-->
...
<!-- some where there is this page that displays initial step via child component -->
<on-boarding-step ...>
<!--- some stuff-->
</on-boarding-step>
...
<!--some stuff-->
</wizard-container>
您可以通过多种方式设置require.
There are many ways you can set up require.
(无前缀) - 在当前元素上找到所需的控制器.如果未找到则抛出错误.
?- 尝试定位所需的控制器,如果未找到,则将 null 传递给链接 fn.
? - Attempt to locate the required controller or pass null to the link fn if not found.
^ - 通过搜索元素及其父元素来定位所需的控制器.如果未找到则抛出错误.
^ - Locate the required controller by searching the element and its parents. Throw an error if not found.
^^ - 通过搜索元素的父元素来定位所需的控制器.如果未找到则抛出错误.
^^ - Locate the required controller by searching the element's parents. Throw an error if not found.
?^ - 尝试通过搜索元素及其父元素来定位所需的控制器,或者如果未找到则将 null 传递给链接 fn.
?^ - Attempt to locate the required controller by searching the element and its parents or pass null to the link fn if not found.
?^^ - 尝试通过搜索元素的父元素来定位所需的控制器,或者如果未找到则将 null 传递给链接 fn.
?^^ - Attempt to locate the required controller by searching the element's parents, or pass null to the link fn if not found.
旧答案:
您需要注入$controller
服务来实例化另一个控制器内的控制器.但请注意,这可能会导致一些设计问题.您始终可以创建遵循单一职责的可重用服务,并根据需要将它们注入控制器.
You need to inject $controller
service to instantiate a controller inside another controller. But be aware that this might lead to some design issues. You could always create reusable services that follows Single Responsibility and inject them in the controllers as you need.
示例:
app.controller('TestCtrl2', ['$scope', '$controller', function ($scope, $controller) {
var testCtrl1ViewModel = $scope.$new(); //You need to supply a scope while instantiating.
//Provide the scope, you can also do $scope.$new(true) in order to create an isolated scope.
//In this case it is the child scope of this scope.
$controller('TestCtrl1',{$scope : testCtrl1ViewModel });
testCtrl1ViewModel.myMethod(); //And call the method on the newScope.
}]);
在任何情况下,您都不能调用 TestCtrl1.myMethod()
,因为您已将方法附加到 $scope
而不是控制器实例上.
In any case you cannot call TestCtrl1.myMethod()
because you have attached the method on the $scope
and not on the controller instance.
如果您要共享控制器,那么最好这样做:-
If you are sharing the controller, then it would always be better to do:-
.controller('TestCtrl1', ['$log', function ($log) {
this.myMethod = function () {
$log.debug("TestCtrl1 - myMethod");
}
}]);
在消费时做:
.controller('TestCtrl2', ['$scope', '$controller', function ($scope, $controller) {
var testCtrl1ViewModel = $controller('TestCtrl1');
testCtrl1ViewModel.myMethod();
}]);
在第一种情况下,$scope
实际上是您的视图模型,而在第二种情况下,它是控制器实例本身.
In the first case really the $scope
is your view model, and in the second case it the controller instance itself.
这篇关于如何在 AngularJS 中将控制器注入另一个控制器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!