Может ли контроллер AngularJS наследовать от другого контроллера в том же модуле?
внутри модуля, контроллер может наследовать свойства от внешнего контроллера:
var app = angular.module('angularjs-starter', []);
var ParentCtrl = function ($scope, $location) {
};
app.controller('ChildCtrl', function($scope, $injector) {
$injector.invoke(ParentCtrl, this, {$scope: $scope});
});
пример через: недоступная ссылка: http://blog.omkarpatil.com/2013/02/controller-inheritance-in-angularjs.html
может ли контроллер внутри модуля наследовать от брата?
var app = angular.module('angularjs-starter', []);
app.controller('ParentCtrl ', function($scope) {
//I'm the sibling, but want to act as parent
});
app.controller('ChildCtrl', function($scope, $injector) {
$injector.invoke(ParentCtrl, this, {$scope: $scope}); //This does not work
});
второй код не работает с $injector.invoke
требует функции в качестве первого параметра и не находит ссылку на ParentCtrl
.
10 ответов
Да, это может, но вы должны использовать $controller
сервис для создания экземпляра контроллера вместо:-
var app = angular.module('angularjs-starter', []);
app.controller('ParentCtrl', function($scope) {
// I'm the sibling, but want to act as parent
});
app.controller('ChildCtrl', function($scope, $controller) {
$controller('ParentCtrl', {$scope: $scope}); //This works
});
в случае, если вы используете vm
синтаксис контроллер, вот мое решение:
.controller("BaseGenericCtrl", function ($scope) {
var vm = this;
vm.reload = reload;
vm.items = [];
function reload() {
// this function will come from child controller scope - RESTDataService.getItemsA
this.getItems();
}
})
.controller("ChildCtrl", function ($scope, $controller, RESTDataService) {
var vm = this;
vm.getItems = RESTDataService.getItemsA;
angular.extend(vm, $controller('BaseGenericCtrl', {$scope: $scope}));
})
к сожалению, вы не можете использовать $controller.call(vm, 'BaseGenericCtrl'...)
, чтобы передать текущий контекст в закрытие (для reload()
) функция, следовательно, только одно решение-использовать this
внутри унаследованной функции для динамического изменения контекста.
Я думаю,вы должны использовать фабрику или услуги,чтобы дать доступные функции или данные для обоих контроллеров.
вот аналогичный вопрос - - ->наследование контроллера AngularJS
в ответ на вопрос, поднятый в этот ответ от gmontague, Я нашел метод наследования контроллера с помощью $controller () и все еще использую синтаксис контроллера "как".
во-первых, используйте синтаксис" as " при наследовании вызова $controller ():
app.controller('ParentCtrl', function(etc...) {
this.foo = 'bar';
});
app.controller('ChildCtrl', function($scope, $controller, etc...) {
var ctrl = $controller('ParentCtrl as parent', {etc: etc, ...});
angular.extend(this, ctrl);
});
затем, в шаблоне HTML, если свойство определено родителем, используйте parent.
для получения свойств, унаследованных от родителя; если определено дочерним, используйте child.
для его получения.
<div ng-controller="ChildCtrl as child">{{ parent.foo }}</div>
Ну, я сделал это по-другому. В моем случае мне нужна функция, которая применяет те же функции и свойства в других контроллерах. Мне это нравилось, за исключением параметров. Таким образом, все ваши ChildCtrls должны получить $location.
var app = angular.module('angularjs-starter', []);
function BaseCtrl ($scope, $location) {
$scope.myProp = 'Foo';
$scope.myMethod = function bar(){ /* do magic */ };
}
app.controller('ChildCtrl', function($scope, $location) {
BaseCtrl.call(this, $scope, $location);
// it works
$scope.myMethod();
});
для тех, кому интересно, вы можете расширить контроллеры компонентов таким же образом, используя метод в принятом ответе.
использовать следующий подход:
родительский компонент (в):
/**
* Module definition and dependencies
*/
angular.module('App.Parent', [])
/**
* Component
*/
.component('parent', {
templateUrl: 'parent.html',
controller: 'ParentCtrl',
})
/**
* Controller
*/
.controller('ParentCtrl', function($parentDep) {
//Get controller
const $ctrl = this;
/**
* On init
*/
this.$onInit = function() {
//Do stuff
this.something = true;
};
});
дочерний компонент (тот, который расширяется):
/**
* Module definition and dependencies
*/
angular.module('App.Child', [])
/**
* Component
*/
.component('child', {
templateUrl: 'child.html',
controller: 'ChildCtrl',
})
/**
* Controller
*/
.controller('ChildCtrl', function($controller) {
//Get controllers
const $ctrl = this;
const $base = $controller('ParentCtrl', {});
//NOTE: no need to pass $parentDep in here, it is resolved automatically
//if it's a global service/dependency
//Extend
angular.extend($ctrl, $base);
/**
* On init
*/
this.$onInit = function() {
//Call parent init
$base.$onInit.call(this);
//Do other stuff
this.somethingElse = true;
};
});
хитрость заключается в использовании именованных контроллеров вместо их определения в определении компонента.
как указано в принятом ответе, вы можете "наследовать" изменения родительского контроллера в $scope и других службах, вызвав:$controller('ParentCtrl', {$scope: $scope, etc: etc});
в контроллере ребенка.
, это не удается, если вы привыкли использовать синтаксис контроллера "как", например, в
<div ng-controller="ChildCtrl as child">{{ child.foo }}</div>
если foo
был установлен в Родительском контроллере (через this.foo = ...
), дочерний контроллер не будет иметь к нему доступа.
как указано в комментариях, вы можете назначить результат $ controller непосредственно в область:
var app = angular.module('angularjs-starter', []);
app.controller('ParentCtrl ', function(etc...) {
this.foo = 'bar';
});
app.controller('ChildCtrl', function($scope, $controller, etc...) {
var inst = $controller('ParentCtrl', {etc: etc, ...});
// Perform extensions to inst
inst.baz = inst.foo + " extended";
// Attach to the scope
$scope.child = inst;
});
Примечание: вы тогда должны удалите часть " как " из ng-controller=
, потому что вы указываете имя экземпляра в коде, а не шаблон.
я использовал синтаксис "Controller as" с vm = this
и хотел наследовать контроллер. У меня были проблемы, если мой родительский контроллер имел функцию, которая изменяла переменную.
используя IProblemFactory это и Салман Аббас ответы, я сделал следующее, чтобы иметь доступ к переменным родительского:
(function () {
'use strict';
angular
.module('MyApp',[])
.controller('AbstractController', AbstractController)
.controller('ChildController', ChildController);
function AbstractController(child) {
var vm = child;
vm.foo = 0;
vm.addToFoo = function() {
vm.foo+=1;
}
};
function ChildController($controller) {
var vm = this;
angular.extend(vm, $controller('AbstractController', {child: vm}));
};
})();
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-controller="ChildController as childCtrl" layout="column" ng-cloak="" ng-app="MyApp">
<button type="button" ng-click="childCtrl.addToFoo()">
add
</button>
<span>
-- {{childCtrl.foo}} --
</span>
</div>
вы можете использовать простой механизм наследования JavaScript. Также не забудьте пройти необходимые угловые службы для вызова.вызов метода.
//simple function (js class)
function baseCtrl($http, $scope, $location, $rootScope, $routeParams, $log, $timeout, $window, modalService) {//any serrvices and your 2
this.id = $routeParams.id;
$scope.id = this.id;
this.someFunc = function(){
$http.get("url?id="+this.id)
.then(success function(response){
....
} )
}
...
}
angular
.module('app')
.controller('childCtrl', childCtrl);
//angular controller function
function childCtrl($http, $scope, $location, $rootScope, $routeParams, $log, $timeout, $window, modalService) {
var ctrl = this;
baseCtrl.call(this, $http, $scope, $location, $rootScope, $routeParams, $log, $timeout, $window, modalService);
var idCopy = ctrl.id;
if($scope.id == ctrl.id){//just for sample
ctrl.someFunc();
}
}
//also you can copy prototype of the base controller
childCtrl.prototype = Object.create(baseCtrl.prototype);