Как ввести контроллер в другой контроллер в 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
должен ли я даже пытаться использовать контроллер внутри другого контроллера, или я должен сделать это услугой?
7 ответов
если ваше намерение состоит в том, чтобы завладеть уже созданным контроллером другого компонента, и если вы следуете подходу на основе компонента / директивы, вы всегда можете require
контроллер (экземпляр компонента) из другого компонента, который следует определенной иерархии.
например:
//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.
},
...
});
теперь использование этих вышеуказанных компонентов может быть чем-то вроде этого:
<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>
существует множество способов настройки требуются.
(без префикса) - найдите необходимый контроллер на текущем элементе. Бросьте ошибку, если не найден.
? - Попытка найти необходимый контроллер или передать null в ссылку fn, если не найден.
^ - Найдите нужный контроллер, поиск элемента и его родителей. Бросьте ошибку, если не найден.
^^ - найдите необходимый контроллер, выполнив поиск родители элемента. Бросьте ошибку, если не найден.
?^ - Попытка найти требуемый контроллер путем поиска элемента и его родителей или передать null в ссылку fn, если не найден.
?^ ^ - Попытка найти требуемый контроллер путем поиска родителей элемента или передать null в ссылку fn, если не найден.
Ответ:
вам нужно впрыснуть $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
- это ваша модель представления, а во втором случае это сам экземпляр контроллера.
Я бы предложил вопрос, который вы должны задать, - это как вводить службы в контроллеры. Тучные обслуживания с тощими регуляторами хорошее эмпирическое правило, ака как раз используют регуляторы для того чтобы склеить ваши обслуживание/фабрику (с логикой дела) в ваши взгляды.
контроллеры собирают мусор при изменении маршрута, поэтому, например, если вы используете контроллеры для хранения бизнес-логики, которая отображает значение, вы потеряете состояние на двух страницах, если пользователь приложения щелкнет браузер назад кнопка.
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();
}]);
вот работает демонстрация завода, введенного в два контроллера
кроме того, я бы предложил иметь прочитайте этот учебник по услугам / фабрикам.
нет необходимости импортировать / вводить контроллер в JS. Вы можете просто ввести контроллер / вложенный контроллер через HTML.У меня получилось. Например:
<div ng-controller="TestCtrl1">
<div ng-controller="TestCtrl2">
<!-- your code-->
</div>
</div>
<div ng-controller="TestCtrl1">
<div ng-controller="TestCtrl2">
<!-- your code-->
</div>
</div>
это лучше всего работает в моем случае, где TestCtrl2 имеет свои собственные директивы.
var testCtrl2 = $controller('TestCtrl2')
Это дает мне ошибку, говоря об ошибке инъекции scopeProvider.
var testCtrl1ViewModel = $scope.$new();
$controller('TestCtrl1',{$scope : testCtrl1ViewModel });
testCtrl1ViewModel.myMethod();
это действительно не работает, если у вас есть директивы в 'TestCtrl1', эта директива фактически имеет другую область действия, чем эта, созданная здесь. Вы получаете два экземпляра "TestCtrl1".
лучшее решение:-
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);})
// вы получили первый вызов контроллера без его выполнениявы также можете использовать $rootScope
чтобы вызвать функцию / метод 1-го контроллера из второго контроллера, как это,
.controller('ctrl1', function($rootScope, $scope) {
$rootScope.methodOf2ndCtrl();
//Your code here.
})
.controller('ctrl2', function($rootScope, $scope) {
$rootScope.methodOf2ndCtrl = function() {
//Your code here.
}
})
используйте typescript для вашего кодирования, потому что это объектно-ориентированный, строго типизированный и простой в обслуживании код ...
для получения дополнительной информации о typescipt нажмите здесь
вот один простой пример, который я создал для обмена данными между двумя контроллерами с помощью 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);
}