Как я вставляю контроллер в другой контроллер в 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
Должен ли я даже пытаться использовать контроллер внутри другого контроллера, или я должен сделать это службой?
Ответы
Ответ 1
Если ваше намерение состоит в том, чтобы заполучить уже созданный экземпляр контроллера другого компонента, и если вы выполняете подход на основе компонента/директивы, вы всегда можете 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 disable method i.e
if(notIsValid(val)){
this.container.disableNext();
}
}
},
...,
require : {
container: '^^wizardContainer' //Require a wizard component 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>
Существует множество способов настроить require.
(без префикса). Найдите требуемый контроллер для текущего элемента. Выброс ошибки, если не найден.
? - Попытайтесь найти требуемый контроллер или передать 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
- ваша модель представления, а во втором случае - сам экземпляр контроллера.
Ответ 2
Я бы предложил вопрос, который вы должны задать, - как вводить услуги в контроллеры. Жирные услуги с тонкими контроллерами - это хорошее эмпирическое правило, так же как и использование контроллеров для приклеивания вашего сервиса / factory (с бизнес-логикой) к вашим представлениям.
Контроллеры получают мусор, собранный при изменениях маршрута, например, если вы используете контроллеры для ведения бизнес-логики, которая отображает значение, вы теряете состояние на двух страницах, если пользователь приложения нажимает кнопку браузера.
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();
}]);
Ниже приведена рабочая демонстрация factory, введенная в два контроллера.
Кроме того, я предложил бы прочитать этот учебник по услугам/фабрикам.
Ответ 3
Нет необходимости импортировать/вставлять ваш контроллер в JS. Вы можете просто ввести контроллер/вложенный контроллер через свой HTML.It работал у меня.
Например:
<div ng-controller="TestCtrl1">
<div ng-controller="TestCtrl2">
<!-- your code-->
</div>
</div>
Ответ 4
<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".
Ответ 5
Лучшее решение: -
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);})
//Здесь вы получили первый вызов контроллера без его выполнения
Ответ 6
вы также можете использовать $rootScope
для вызова функции/метода 1-го контроллера со второго контроллера, например,
.controller('ctrl1', function($rootScope, $scope) {
$rootScope.methodOf2ndCtrl();
//Your code here.
})
.controller('ctrl2', function($rootScope, $scope) {
$rootScope.methodOf2ndCtrl = function() {
//Your code here.
}
})
Ответ 7
используйте 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);
}