Как я могу ввести контроллер в другой контроллер в 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
это ваша модель представления, а во втором случае это сам экземпляр контроллера.
Я бы предложил вопрос, который вы должны задать, заключается в том, как вводить службы в контроллеры. Fat services с тощими контроллерами-это хорошее эмпирическое правило, а также просто используйте контроллеры для склеивания вашего сервиса/фабрики (с бизнес-логикой) в ваши представления.
контроллеры собирают мусор при изменении маршрута, поэтому, например, если вы используете контроллеры для хранения бизнес-логики, которая отображает значение, вы потеряете состояние на двух страницах, если пользователь приложения щелкнет браузер обратно кнопка.
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(); }]);
вот такой рабочий демонстрация фабрики впрыснутой в 2 регулятора
кроме того, я бы предложил иметь прочитайте этот учебник по услугам / фабрикам.
нет необходимости импортировать / вводить контроллер в JS. Вы можете просто ввести свой контроллер / вложенный контроллер через ваш HTML.It-он работал на меня. Например:
<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);
}