如何在AngularJS中将一个控制器注入到另一个控制器中
如何在AngularJS中将一个控制器注入到另一个控制器中
我刚接触Angular,试图弄清楚如何做一些事情...
在使用AngularJS时,我该如何注入一个控制器以在另一个控制器中使用?
我有以下代码片段:
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(); }]);
当我执行这段代码时,我得到错误:
Error: [$injector:unpr] Unknown provider: TestCtrl1Provider <- TestCtrl1 http://errors.angularjs.org/1.2.21/$injector/unpr?p0=TestCtrl1Provider%20%3C-%20TestCtrl1
我是否应该试图在另一个控制器中使用一个控制器,还是应该将其作为一个服务?
在AngularJS中,如果您的目标是获取另一个组件的已实例化控制器,并且您正在遵循组件/指令的方法,您可以始终从遵循某个层次结构的另一个组件中require
一个控制器(组件的实例)。
解决方法如下:
首先,在容器组件中定义一个控制器,以提供向导并透明传递在向导中显示的页面组件:
myModule.component('wizardContainer', { ..., controller : function WizardController() { this.disableNext = function() { //disable next step... some implementation to disable the next button hosted by the wizard } }, ... });
然后,在子组件中定义一个控制器,并在$onInit
方法中访问容器的disableNext()
方法:
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. }, ... });
最后,使用这些组件的示例可能如下所示:
... ...
这是使用require
的几种设置方法:
(no prefix) - Locate the required controller on the current element. Throw an error if not found. ? - 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. ?^ - Attempt to locate the required controller by searching the element and its parents or pass null to the link fn if not found. ?^^ - Attempt to locate the required controller by searching the element's parents, or pass null to the link fn if not found.
另外,您还可以使用$controller
服务在一个控制器中实例化另一个控制器。但是请注意,这可能会导致一些设计问题。您始终可以创建可重用的服务,遵循单一职责,并根据需要在控制器中注入它们。
示例:
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
上而不是控制器实例上。
如果要共享控制器,最好的做法是:
.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
是您的视图模型,而在第二种情况下,它是控制器实例本身。
这取决于控制器提供的功能。如果它更像是一个需要在组件之间共享的视图模型,那么可以采用第一种方式。但如果它更像是一个服务提供者功能,那么最好创建一个服务。
在上述示例中,您正在通过指令控制器访问容器,但我无法让它起作用。我可以通过指令本身的第四个参数在链接函数中访问所需的控制器。但是它们没有像上面的示例中那样绑定到指令控制器。是否还有其他人遇到这个问题?
在AngularJS中,如何将一个控制器注入到另一个控制器中,这个问题的出现是因为作者建议应该询问如何将服务注入到控制器中。在控制器中使用服务来处理业务逻辑,并将其与视图关联起来是一个很好的原则。控制器在路由更改时会被垃圾回收,所以如果使用控制器来保存渲染值的业务逻辑,当应用程序用户点击浏览器的后退按钮时,您将会丢失两个页面的状态。
以下是一个示例代码,演示了如何将工厂注入到两个控制器中:
var app = angular.module("testApp", ['']); app.factory('methodFactory', function () { return { myMethod: function () { console.log("methodFactory - myMethod"); } }; }); app.controller('TestCtrl1', ['$scope', 'methodFactory', function ($scope, methodFactory) { $scope.mymethod1 = methodFactory.myMethod(); }]); app.controller('TestCtrl2', ['$scope', 'methodFactory', function ($scope, methodFactory) { $scope.mymethod2 = methodFactory.myMethod(); }]);
您可以通过访问此处的演示来查看工厂如何注入到两个控制器中的完整示例。
此外,建议阅读这篇关于服务/工厂的教程,以获得更多信息。
这是因为在AngularJS中,可以通过HTML来注入控制器(controller),而不需要在JS中导入或注入控制器。可以通过在HTML中嵌套使用`ng-controller`指令来注入控制器。
解决方法是将所有共同的元素放入一个服务(service)中,并将该服务注入到相应的控制器(controller)中。
如下所示的HTML代码演示了如何通过HTML来注入控制器:
在上述代码中,`TestCtrl2`控制器被嵌套在`TestCtrl1`控制器中。
另一种解决方法是将共同的元素放入一个服务中,然后将该服务注入到相应的控制器中。通过这种方式,可以避免在HTML中嵌套控制器,使代码更加清晰和可维护。
希望以上内容对您有所帮助。