Un contrôleur AngularJS peut-il hériter d'un autre contrôleur dans le même module?
dans un module, un contrôleur peut hériter des propriétés d'un contrôleur extérieur:
var app = angular.module('angularjs-starter', []);
var ParentCtrl = function ($scope, $location) {
};
app.controller('ChildCtrl', function($scope, $injector) {
$injector.invoke(ParentCtrl, this, {$scope: $scope});
});
exemple via: lien mort : http://blog.omkarpatil.com/2013/02/controller-inheritance-in-angularjs.html
Peut aussi un contrôleur à l'intérieur d'un module d'hériter d'un frère?
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
});
le deuxième code ne fonctionne pas depuis $injector.invoke
nécessite une fonction comme premier paramètre et ne trouve pas la référence à ParentCtrl
.
10 réponses
Oui, il peut, mais vous devez utiliser le service $controller
pour instancier le contrôleur à la place: -
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
});
dans le cas où vous utilisez vm
syntaxe du contrôleur , voici ma solution:
.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}));
})
malheureusement, vous ne pouvez pas utiliser $controller.call(vm, 'BaseGenericCtrl'...)
, pour passer le contexte actuel dans la fonction de fermeture (pour reload()
), donc une seule solution est d'utiliser this
dans la fonction héritée afin de changer dynamiquement le contexte.
je pense,vous devriez utiliser l'usine ou le service,pour donner des fonctions accessibles ou des données pour les deux contrôleurs.
voici une question similaire - - - > AngularJS contrôleur héritage
en réponse à la question soulevée dans cette réponse de gmontague , j'ai trouvé une méthode pour hériter un controller en utilisant $controller(), et toujours utiliser le controller" as " syntaxe.
tout D'abord, utilisez "comme" syntaxe lorsque vous héritez appelant $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);
});
puis, dans le modèle HTML, si la propriété est définie par parent, puis utiliser parent.
pour récupérer les propriétés héritées de parent; si défini par enfant, puis utilisez child.
pour le récupérer.
<div ng-controller="ChildCtrl as child">{{ parent.foo }}</div>
J'ai fait ça d'une autre manière. Dans mon cas, je voulais une fonction qui appliquent les mêmes fonctions et les propriétés dans d'autres contrôleurs. J'ai bien aimé, sauf par des paramètres. De cette façon, tous vos enfants ont besoin de recevoir $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();
});
pour ceux qui se demandent, vous pouvez étendre les contrôleurs de composants de la même manière, en utilisant la méthode dans la réponse acceptée.
utiliser l'approche suivante:
composant Parent (à étendre de):
/**
* 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;
};
});
composant enfant (le seul s'étendant):
/**
* 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;
};
});
le truc est d'utiliser des contrôleurs nommés, au lieu de les définir dans la définition du composant.
comme mentionné dans la réponse acceptée, vous pouvez" hériter "des modifications d'un contrôleur parent à $scope et autres services en appelant: $controller('ParentCtrl', {$scope: $scope, etc: etc});
dans votre contrôleur enfant.
Toutefois , il échoue si vous êtes habitué à l'utilisation de la manette " a " de la syntaxe, par exemple dans
<div ng-controller="ChildCtrl as child">{{ child.foo }}</div>
si foo
a été défini dans le contrôleur parent (via this.foo = ...
), le contrôleur enfant n'y aura pas accès.
comme mentionné dans les commentaires, vous pouvez attribuer le résultat de $controller directement à la portée:
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;
});
Note: vous alors devez supprimer la partie " as " de ng-controller=
, parce que vous spécifiez le nom de l'instance dans le code, et non plus le modèle.
j'utilisais la syntaxe" Controller as "avec vm = this
et je voulais hériter d'un controller. J'avais des problèmes si mon contrôleur parent avait une fonction qui modifiait une variable.
à l'Aide IProblemFactory et Salman Abbas des réponses, je n'ai la suite d'avoir accès à des variables parents:
(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>
vous pouvez utiliser un mécanisme D'héritage JavaScript simple. Aussi, n'oubliez pas de passer des services tout à fait angulaires à invoquer de .appel de la méthode.
//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);
Désignent ci-après le lien pour AngularJs inheritences feartue.