I'm new to Angular and trying to figure out how to do things...
我对角度不太熟悉,也不知道怎么做……
Using AngularJS, how can I inject a controller to be used within another controller?
使用AngularJS,如何在另一个控制器中注入要使用的控制器?
I have the following snippet:
我有以下片段:
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?
我应该尝试在另一个控制器中使用一个控制器,还是应该将其作为服务?
129
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.
如果您的目的是获得另一个组件的已经实例化的控制器,并且如果您遵循基于组件/指令的方法,您总是可以从遵循一定层次结构的另一个组件中要求一个控制器(组件的实例)。
For example:
例如:
//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:
以上这些组件的用法大概是这样的:
...
...
There are many ways you can set up 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.
吗?-试图找到所需的控制器或将null传递给link fn(如果没有找到的话)。
^ - 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.
? ^ -试图定位所需的控制器通过搜索元素及其父母或null传递给链接fn如果没有找到。
?^^ - Attempt to locate the required controller by searching the element's parents, or pass null to the link fn if not found.
? ^ ^,试图找到所需的控制器通过搜索元素的父母,或null传递给链接fn如果没有发现。
Old Answer:
旧的回答:
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.
您需要注入$controller服务来实例化另一个控制器中的控制器。但是要注意这可能会导致一些设计问题。您可以始终创建遵循单个职责的可重用服务,并根据需要将它们注入控制器中。
Example:
例子:
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.
}]);
In any case you cannot call TestCtrl1.myMethod()
because you have attached the method on the $scope
and not on the controller instance.
在任何情况下,您都不能调用TestCtrl1.myMethod(),因为您在$scope上附加了方法,而不是在controller实例上。
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");
}
}]);
and while consuming do:
虽然消费:
.controller('TestCtrl2', ['$scope', '$controller', function ($scope, $controller) {
var testCtrl1ViewModel = $controller('TestCtrl1');
testCtrl1ViewModel.myMethod();
}]);
In the first case really the $scope
is your view model, and in the second case it the controller instance itself.
在第一种情况下,$作用域是视图模型,在第二种情况下是控制器实例本身。
33
I'd suggest the question you should be asking is how to inject services into controllers. Fat services with skinny controllers is a good rule of thumb, aka just use controllers to glue your service/factory (with the business logic) into your views.
我建议你应该问的问题是如何向控制器注入服务。使用瘦控制器的胖服务是一个很好的经验法则,也就是使用控制器将您的服务/工厂(使用业务逻辑)粘到您的视图中。
Controllers get garbage collected on route changes, so for example, if you use controllers to hold business logic that renders a value, your going to lose state on two pages if the app user clicks the browser back button.
控制器在路径更改时收集垃圾,因此,例如,如果您使用控制器来保存呈现值的业务逻辑,如果应用程序用户单击浏览器后退按钮,您将在两个页面上丢失状态。
var app = angular.module("testApp", ['']);
app.factory('methodFactory', function () {
return { myMethod: function () {
console.log("methodFactory - myMethod");
};
};
app.controller('TestCtrl1', ['$scope', 'methodFactory', function ($scope,methodFactory) { //Comma was missing here.Now it is corrected.
$scope.mymethod1 = methodFactory.myMethod();
}]);
app.controller('TestCtrl2', ['$scope', 'methodFactory', function ($scope, methodFactory) {
$scope.mymethod2 = methodFactory.myMethod();
}]);
Here is a working demo of factory injected into two controllers
这是一个工厂注入到两个控制器的工作演示
Also, I'd suggest having a read of this tutorial on services/factories.
另外,我建议您阅读一下关于服务/工厂的教程。
12
There is no need to import/Inject your controller in JS. You can just inject your controller/nested controller through your HTML.It's worked for me. Like :
不需要在JS中导入/注入控制器。您可以通过HTML注入您的控制器/嵌套控制器。它为我工作。如:
-1
This works best in my case, where TestCtrl2 has it's own directives.
在我的例子中,这是最有效的,TestCtrl2有它自己的指令。
var testCtrl2 = $controller('TestCtrl2')
This gives me an error saying scopeProvider injection error.
这给了我一个错误,说scopeProvider注入错误。
var testCtrl1ViewModel = $scope.$new();
$controller('TestCtrl1',{$scope : testCtrl1ViewModel });
testCtrl1ViewModel.myMethod();
This doesn't really work if you have directives in 'TestCtrl1', that directive actually have a different scope from this one created here. You end up with two instances of 'TestCtrl1'.
如果你在“testctrl - l1”中有指令,那么这个指令实际上与这里创建的这个指令有不同的作用域。最后得到两个'TestCtrl1'实例。
-1
The best solution:-
最好的解决方案:-
angular.module("myapp").controller("frstCtrl",function($scope){$scope.name="Atul Singh";}).controller("secondCtrl",function($scope){angular.extend(this, $controller('frstCtrl', {$scope:$scope}));console.log($scope);})
// Here you got the first controller call without executing it
//这里你得到了第一个控制器调用,但没有执行它
-1
you can also use $rootScope
to call a function/method of 1st controller from second controller like this,
你也可以使用$rootScope从第二个控制器调用第一个控制器的函数/方法,
.controller('ctrl1', function($rootScope, $scope) {
$rootScope.methodOf2ndCtrl();
//Your code here.
})
.controller('ctrl2', function($rootScope, $scope) {
$rootScope.methodOf2ndCtrl = function() {
//Your code here.
}
})
-2
use typescript for your coding, because it's object oriented, strictly typed and easy to maintain the code ...
为您的代码使用打字稿,因为它是面向对象的,严格的类型和易于维护的代码……
for more info about typescipt click here
有关排版的更多信息请点击这里
Here one simple example I have created to share data between two controller using Typescript...
这里我创建了一个简单的示例,用于使用Typescript在两个控制器之间共享数据。
module Demo {
//create only one module for single Applicaiton
angular.module('app', []);
//Create a searvie to share the data
export class CommonService {
sharedData: any;
constructor() {
this.sharedData = "send this data to Controller";
}
}
//add Service to module app
angular.module('app').service('CommonService', CommonService);
//Create One controller for one purpose
export class FirstController {
dataInCtrl1: any;
//Don't forget to inject service to access data from service
static $inject = ['CommonService']
constructor(private commonService: CommonService) { }
public getDataFromService() {
this.dataInCtrl1 = this.commonService.sharedData;
}
}
//add controller to module app
angular.module('app').controller('FirstController', FirstController);
export class SecondController {
dataInCtrl2: any;
static $inject = ['CommonService']
constructor(private commonService: CommonService) { }
public getDataFromService() {
this.dataInCtrl2 = this.commonService.sharedData;
}
}
angular.module('app').controller('SecondController', SecondController);
}
}