Can an AngularJS controller inherit from another controller in the same module?
Solution 1
Yes, it can but you have to use the $controller
service to instantiate the controller instead:-
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
});
Solution 2
In case you are using vm
controller syntax, here is my 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}));
})
Unfortunately, you can't use $controller.call(vm, 'BaseGenericCtrl'...)
, to pass current context into closure (for reload()
) function, hence only one solution is to use this
inside inherited function in order to dynamically change context.
Solution 3
In response to the issue raised in this answer by gmontague, I have found a method to inherit a controller using $controller(), and still use the controller "as" syntax.
Firstly, use "as" syntax when you inherit calling $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);
});
Then, in HTML template, if the property is defined by parent, then use parent.
to retrieve properties inherited from parent; if defined by child, then use child.
to retrieve it.
<div ng-controller="ChildCtrl as child">{{ parent.foo }}</div>
Solution 4
I think,you should use factory or service,to give accessible functions or data for both controllers.
here is similar question ---> AngularJS controller inheritance
Solution 5
Well, I did this in another way. In my case I wanted a function that apply the same functions and properties in other controllers. I liked it, except by parameters. In this way, all yours ChildCtrls need to receive $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();
});
Related videos on Youtube
Federico Elles
Updated on January 29, 2020Comments
-
Federico Elles over 4 years
Within a module, a controller can inherit properties from an outside controller:
var app = angular.module('angularjs-starter', []); var ParentCtrl = function ($scope, $location) { }; app.controller('ChildCtrl', function($scope, $injector) { $injector.invoke(ParentCtrl, this, {$scope: $scope}); });
Example via: Dead link:
http://blog.omkarpatil.com/2013/02/controller-inheritance-in-angularjs.htmlCan also a controller inside a module inherit from a sibling?
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 });
The second code does not work since
$injector.invoke
requires a function as first parameter and does not find the reference toParentCtrl
.-
Bart almost 11 yearsThis should help: stackoverflow.com/questions/16828287/…
-
alockwood05 over 9 yearsaside: this doesn't look like inheritance, but more like sharing methods or injecting. Perhaps just semantics.
-
AlexS about 9 yearsThe link for the example isn't valid anymore.
-
Federico Elles about 9 yearsGoogle Cache Link: webcache.googleusercontent.com/… which points to this interesting Fiddle: jsfiddle.net/mhevery/u6s88/12
-
-
gontard over 10 years
ParentCtrl
should be acontroller
or is it possible to use aservice
? -
ZeissS over 10 years@gontard: In this case it must be a controller, as
$controller
can only use registered controllers. -
To Ka over 9 yearsIt is a very good solution. Thank you. But how would I do it in case I am using Controller As syntax?
-
Salman von Abbas over 9 years@ToKa Same as other controllers?
ChildCtrl as toka
-
To Ka over 9 yearsYes that is one way, thanks. I came across that post when I was searching for solution. I was thinking if there was some way to load controller function and extend "this" with it.
-
Salman von Abbas over 9 years@ToKa What are you referring to by "Controller As syntax"? Show me some code.
-
Robbo_UK over 9 yearsHow is it done with controller as?.. the jsfiddle above does not include it?
-
Dan over 9 yearsThe above fiddle was asked as a question. It's worth noting that controllerAs simply assigns the controller to the scope - So you would change
$scope
tothis
(in theory) -
opewix over 9 years@DanPantry Thanks, replacing
$scope
tothis
allows usage ofcontroller as
syntax -
Ryan Mann almost 9 yearsThis worked for me, however I'm trying to do this in a way that I have the parent controller and the child controller on the same page. This causes the $http operation in the parent controller to run twice. When the child controller injects the scope of the parent controller my $scope.AllMembers array get's populated twice as the parent controller causes it to run, then the child controller causes it to run again. Is there any way to prevent that?
-
Z2VvZ3Vp almost 9 yearsI would like to have a universal
loading
variable so that when data is loading I always do the same thing, I don't think factories can do that. My parent controller can have a loading variable but the factory can't manipulate it... right?! -
IProblemFactory over 8 yearsFor people looking for solution with
var vm = this
convention: stackoverflow.com/a/34113156/140070 -
herringtown about 8 yearsCouldn't you have just done this instead ? > $controller('BaseGenericControl', { vm: vm });
-
IProblemFactory about 8 years
vm
is just a variable inside controller, I don't think so Angular could use it as expected. -
gm2008 about 8 yearsUsing "controller as" syntax has no problem. See my answer: stackoverflow.com/a/36549465/2197555
-
trueboroda about 7 yearshow to be with other services not $scope that injected in the parent and chilld controllers. For instance, how can we use $routeParams in the parent controller? Is the parent's and child's services independed?
-
Nathan about 7 years$controller documentation: docs.angularjs.org/api/ngMock/service/$controller
-
Radu Linu over 5 yearsDon't forget to declare the
$controller
in theChildCtrl
.