Controller Inheritance

8,656 views
Skip to first unread message

zdam

unread,
Mar 30, 2012, 2:51:11 AM3/30/12
to ang...@googlegroups.com
Hi,

I'm trying to figure out how to use controller inheritance.

This fiddle shows my attempt: http://jsfiddle.net/zdam/UZrVS/


I would like to be able to call methods on the base controller from within my view, which is being controlled by a DerivedController.

Note in the example there is no linkage between the BaseController and DerivedController, this is what I need help with.

Thanks,

Adam.

John Lindquist

unread,
Mar 30, 2012, 3:09:31 AM3/30/12
to ang...@googlegroups.com
Hopefully this helps:

From what I understand, Controller inheritance is based on the DOM hierarchy.

I also created a "model" object on the $scope instead of just overriding the "name" property each time.

Cheers,
John

--
You received this message because you are subscribed to the Google Groups "AngularJS" group.
To view this discussion on the web visit https://groups.google.com/d/msg/angular/-/2BemXDo-KvgJ.
To post to this group, send email to ang...@googlegroups.com.
To unsubscribe from this group, send email to angular+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/angular?hl=en.

Krzysztof Danielewicz

unread,
Mar 30, 2012, 3:34:29 AM3/30/12
to ang...@googlegroups.com
here is my solution:

in docs there is the section titled "Controller Inheritance Example"

KD

zdam

unread,
Mar 30, 2012, 4:33:30 AM3/30/12
to ang...@googlegroups.com
OK, what about a way that doesn't require nesting of controllers in the view - just a pure javascript inheritance mechanism?

Witold Szczerba

unread,
Mar 30, 2012, 8:18:20 AM3/30/12
to ang...@googlegroups.com
On 30 March 2012 09:09, John Lindquist <johnli...@gmail.com> wrote:
> Hopefully this helps:
> http://jsfiddle.net/johnlindquist/UZrVS/29/
>
> From what I understand, Controller inheritance is based on the DOM
> hierarchy.

This is no longer true (since version 1.0rc1), see changelog:
https://github.com/angular/angular.js/blob/master/CHANGELOG.md#1.0.0rc1

Regards,
Witold Szczerba

Witold Szczerba

unread,
Mar 30, 2012, 8:22:28 AM3/30/12
to ang...@googlegroups.com
OK, to make it clear, as I can see now - you are using most recent
version in your example.
Scope objects ($scope instances) inheritance is based on the DOM,
controllers are not. It is up to you to inherit one controller from
another and it has nothing to do with DOM any more.

--
Witold Szczerba

Raj

unread,
Mar 30, 2012, 10:29:29 AM3/30/12
to AngularJS
Witold,
So if you do need direct controller inheritance, how would you do
this?
Also, is DOM based inheritance achieved purely by nesting one
controller inside another in the HTML template?
Regards,
Raj

On Mar 30, 7:22 am, Witold Szczerba <pljosh.m...@gmail.com> wrote:
> OK, to make it clear, as I can see now - you are using most recent
> version in your example.
> Scope objects ($scope instances) inheritance is based on the DOM,
> controllers are not. It is up to you to inherit one controller from
> another and it has nothing to do with DOM any more.
>
> --
> Witold Szczerba
>
> On 30 March 2012 14:18, Witold Szczerba <pljosh.m...@gmail.com> wrote:

Witold Szczerba

unread,
Mar 30, 2012, 1:48:31 PM3/30/12
to ang...@googlegroups.com
Hi again, see my comments inline.

On 30 March 2012 16:29, Raj <rvaur...@gmail.com> wrote:
> Witold,
> So if you do need direct controller inheritance, how would you do
> this?

This has nothing to do with AngularJS, it is the JavaScript stuff.
There is very helpful presentation, by anyone else but Misko himself,
about JavaScript the language:
http://misko.hevery.com/2010/07/14/how-javascript-works/
It is one hour long. If you are going to write JavaScript code for
longer than few days in your life, then I would strongly recommend it.

> Also, is DOM based inheritance achieved purely by nesting one
> controller inside another in the HTML template?

Again, since AngularJS 1.0rc1, controller inheritance has nothing to
do with DOM. You can inherit one controller from another by yourself
if you wish, but the DOM hierarchy does influence nothing but $scope
objects, which may be injected into controllers.
Directives like ngController, or more generally, the template compiler
instantiates controllers and injects all the things they explicitly
want. The injection context also contains $scope and that scope
instance inherits from other $scope object, upper in hierarchy, up to
the $rootScope which is the uber-mother of all scopes.

So, the bottom line is:
var yourController = new YourController(injectables_goes_here);

Whether "yourController.doSomething()" method exist in that
controller, or in some (pseudo) super class (JavaScript does not have
classes, right?) - it is up to you.

I hope this helped :)

Regards,
Witold Szczerba

> Regards,
> Raj
>
> On Mar 30, 7:22 am, Witold Szczerba <pljosh.m...@gmail.com> wrote:
>> OK, to make it clear, as I can see now - you are using most recent
>> version in your example.
>> Scope objects ($scope instances) inheritance is based on the DOM,
>> controllers are not. It is up to you to inherit one controller from
>> another and it has nothing to do with DOM any more.
>>
>> --
>> Witold Szczerba
>>
>> On 30 March 2012 14:18, Witold Szczerba <pljosh.m...@gmail.com> wrote:
>>
>>
>>
>>
>>
>>
>>
>> > On 30 March 2012 09:09, John Lindquist <johnlindqu...@gmail.com> wrote:
>> >> Hopefully this helps:
>> >>http://jsfiddle.net/johnlindquist/UZrVS/29/
>>
>> >> From what I understand, Controller inheritance is based on the DOM
>> >> hierarchy.
>>
>> > This is no longer true (since version 1.0rc1), see changelog:
>> >https://github.com/angular/angular.js/blob/master/CHANGELOG.md#1.0.0rc1
>>
>> > Regards,
>> > Witold Szczerba
>

> --
> You received this message because you are subscribed to the Google Groups "AngularJS" group.

Raj

unread,
Mar 30, 2012, 1:57:45 PM3/30/12
to AngularJS
Witold,
Thanks for the response. I am enclosing an example from the dev guides
- there is nothing inherent within the declaration of the controllers
to imply inheritance. However, the way the controllers are being used
in the template shows a nesting of elements. Does this nesting imply
inheritance? I hope I am asking the right question :-)

<body ng-controller="MainCtrl">
<p>Good {{timeOfDay}}, {{name}}!</p>
<div ng-controller="ChildCtrl">
<p>Good {{timeOfDay}}, {{name}}!</p>
<p ng-controller="BabyCtrl">Good {{timeOfDay}}, {{name}}!</p>
</body>

function MainCtrl($scope) {
$scope.timeOfDay = 'morning';
$scope.name = 'Nikki';
}

function ChildCtrl($scope) {
$scope.name = 'Mattie';
}

function BabyCtrl($scope) {
$scope.timeOfDay = 'evening';
$scope.name = 'Gingerbreak Baby';
}

Regards,
Raj

On Mar 30, 12:48 pm, Witold Szczerba <pljosh.m...@gmail.com> wrote:
> Hi again, see my comments inline.
>

zdam

unread,
Mar 30, 2012, 6:39:29 PM3/30/12
to ang...@googlegroups.com

In particular I am after an example that does *not* require nested controllers in the html.


I have used angular.extend(this, new BaseController($scope))  inside the constructor function of the DerivedController, however this means I am newing up the DerivedController directly.  If is has other dependencies not available to the DerivedController then this will not work.

- Is there some way I can use the DI facilities of angular to have angular create the BaseController for me? 

zdam

unread,
Mar 31, 2012, 12:58:46 AM3/31/12
to ang...@googlegroups.com
Further to this I have tried using DI by registering the controller using module.controller(...)

and then tried to retrieve that controller using both $controller(...) and $injector.get(...)

unsuccessfully :(  

zdam

unread,
Mar 31, 2012, 4:51:07 PM3/31/12
to ang...@googlegroups.com
I now have a much simpler solution:

Place the common code back into a service.

Use angular.extend to extend the scope with those service methods.

Now these methods can be called directly from markup, which is what I wanted.

One outstanding question: How can I refer to $scope when inside markup eg.  ng-click="someMethodCall($scope)"    <== how do I refer to $scope ?


Cheers, Adam

Peter Bacon Darwin

unread,
Mar 31, 2012, 4:57:39 PM3/31/12
to ang...@googlegroups.com
Not sure if I like the idea of merging service methods into the scope, or passing the scope into the service for that matter but anyway you can access the scope from the template by simply using "this": http://jsfiddle.net/KV5uw/25/
Pete

--
You received this message because you are subscribed to the Google Groups "AngularJS" group.
To view this discussion on the web visit https://groups.google.com/d/msg/angular/-/LTaBnLNCWMEJ.

zdam

unread,
Mar 31, 2012, 7:06:35 PM3/31/12
to ang...@googlegroups.com
Thanks, I'm not sure I like the idea of using a service this way either. All I want to be able to do is re-use some common code across controllers, and also be able to invoke this common code directly from the html.

How would you achieve this?
Pete

To unsubscribe from this group, send email to angular+unsubscribe@googlegroups.com.

Elliott Sprehn

unread,
Apr 1, 2012, 12:38:20 PM4/1/12
to ang...@googlegroups.com
On Sat, Mar 31, 2012 at 4:06 PM, zdam <adam.k...@gmail.com> wrote:
Thanks, I'm not sure I like the idea of using a service this way either. All I want to be able to do is re-use some common code across controllers, and also be able to invoke this common code directly from the html.

How would you achieve this?


Using normal JS inheritance and putting the methods on $scope. If the Parent controller intended the method to be exposed to the scope then this should just work.

ex.

function Parent($scope) {
  $scope.compute = function(a,b) { return a + b; };
}

function Child($scope, $injector) {
  // Call the super constructor.
  $injector.invoke(Parent, this);
};
Child.prototype = Object.create(Parent.prototype);

If the parent controller didn't intend the method to be exposed you'd need to assign it to $scope manually, but I'd question exposing a method directly to views that the parent Controller didn't already intend to expose.

- Elliott

Witold Szczerba

unread,
Apr 1, 2012, 6:28:14 PM4/1/12
to ang...@googlegroups.com
Hi,
can you provide some real use-case?
I am asking, because in typical angular app, to reuse template
artifacts, one writes/uses directives or filters, and to reuse
controller logic - there are services. And if you really have a
hierarchy in template, then you are supposed to reflect that by
defining controller inside another one in markup. Additionally you can
subclass controllers using plain-old JavaScript, but (again and again)
I am reminding that since 1.0rc1, Angular has nothing to do with
controller inheritance, only $scope get assigned parent $scope (in
markup hierarchy) as a prototype.

Regards,
Witold Szczerba

>>> angular+u...@googlegroups.com.


>>> For more options, visit this group at
>>> http://groups.google.com/group/angular?hl=en.
>>
>>

> --
> You received this message because you are subscribed to the Google Groups
> "AngularJS" group.
> To view this discussion on the web visit

> https://groups.google.com/d/msg/angular/-/vLg1-UrMNHMJ.


>
> To post to this group, send email to ang...@googlegroups.com.
> To unsubscribe from this group, send email to

> angular+u...@googlegroups.com.

zdam

unread,
Apr 1, 2012, 7:36:30 PM4/1/12
to ang...@googlegroups.com
Hi,

The $injector.invoke call is raising an error:   Error: Unknown provider: $scopeProvider <- $scope

zdam

unread,
Apr 1, 2012, 7:45:33 PM4/1/12
to ang...@googlegroups.com
Hi,

The real-world use-case is that my team is going to be building a bunch of crud forms.

Each form has a bunch of similar work to do - use a resource to retrieve and save data, display errors etc etc.

I want to pull common stuff out of these crud forms.

Some of the common stuff has moved to a wrapped resource that does pre/post processing, some of the stuff has moved to services, some of the stuff has moved to directives.

The particular piece I am working on now, should long-term move to a directive, but in short-term (ie not committing to more complex task of writing a directive), I simply want to get the code out of each controller but available to the view.

Cheers, Adam.

>>> angular+unsubscribe@googlegroups.com.


>>> For more options, visit this group at
>>> http://groups.google.com/group/angular?hl=en.
>>
>>
> --
> You received this message because you are subscribed to the Google Groups
> "AngularJS" group.
> To view this discussion on the web visit
> https://groups.google.com/d/msg/angular/-/vLg1-UrMNHMJ.
>
> To post to this group, send email to ang...@googlegroups.com.
> To unsubscribe from this group, send email to

> angular+unsubscribe@googlegroups.com.

Misko Hevery

unread,
Apr 2, 2012, 7:30:17 PM4/2/12
to ang...@googlegroups.com
http://jsfiddle.net/mhevery/u6s88/12/

$scope is not a service but injection local, which is why you were getting an error.

This is just a standart javascript way of declaring inheritance. the only tricky part is the call to supper to take advantage of the injection.

To view this discussion on the web visit https://groups.google.com/d/msg/angular/-/btEyiX4-O1kJ.

To post to this group, send email to ang...@googlegroups.com.
To unsubscribe from this group, send email to angular+u...@googlegroups.com.

ItsLeeOwen

unread,
Apr 9, 2012, 8:27:28 PM4/9/12
to ang...@googlegroups.com
Is there a way to reference the parent scope from a child scope, in the view?

<body ng-controller="MainCtrl"> 
 <div ng-controller="ChildCtrl"> 
   <p>{{parent.someProp}} or {{MainCtrl.someProp}}</p>
</body>


ItsLeeOwen

unread,
Apr 9, 2012, 8:46:30 PM4/9/12
to ang...@googlegroups.com
Found it:  {{$parent.someProp}}


Kelly Milligan

unread,
Sep 5, 2013, 5:17:05 PM9/5/13
to ang...@googlegroups.com, mi...@hevery.com
Hello, I know this is an older post, but I am trying to find a bit more specific example on this topic. when structuring a larger app, is it suggested that to do the inheritance a developer should just have their own namespace for the constructors and methods to put classes under, then do the  inheritance all through that?  then assign the controller through the modules controller method??

my app is largely structured in the following fashion:

angular.module('testCtrl', [])
    .controller('testCtrl', function ($scope) {

      $scope.something = 'value';

    });

I am able to separate out the constructor into a more typical js constructor pattern with it's own methods, etc, in the file for this module pretty easily, but what is the suggested way to have classes in separate files with angular and have inheritance?  Are there angular methods I can use in the module system to load a parent class via DI then extend it with the child class? maybe through a factory or a service?

>>> angular+u...@googlegroups.com.
>>> For more options, visit this group at
>>> http://groups.google.com/group/angular?hl=en.
>>
>>

> --
> You received this message because you are subscribed to the Google Groups
> "AngularJS" group.
> To view this discussion on the web visit
> https://groups.google.com/d/msg/angular/-/vLg1-UrMNHMJ.
>
> To post to this group, send email to ang...@googlegroups.com.
> To unsubscribe from this group, send email to

--
You received this message because you are subscribed to the Google Groups "AngularJS" group.

Itamar Rogel

unread,
Dec 8, 2013, 4:49:04 PM12/8/13
to ang...@googlegroups.com, mi...@hevery.com
Hi Kelly,
Bounced on your post while searching for something...

If I understood you correctly and you want to share code in a way similar to what was illustrated previously in this thread, but with using the angular.Module.controller() controller definition style, something like this might be what you're after:

var controllers = angular.module('myControllers', []);

// The base controller, containing shared logic
// Run any initialization logic and populate the given $scope with data & view-accessible
// code as necessary
controllers.controller('BaseController', ['$scope', 'MyService', function($scope, MyService) {
        
    console.log("I have been called with scope: ", $scope);

    $scope.mySharedLogic = function() {
        // ... Do something ...
    };
}]);
    
controllers.controller('ChildControllerOne', ['$controller', '$scope', 'MyOtherService', function($controller, $scope, MyOtherService) {

    $controller('BaseController', {$scope: $scope});

    // $scope now has mySharedLogic 
}]);
        
// Thrown in some other dependencies for example's sake
controllers.controller('ChildControllerTwo', ['$controller', '$scope', '$routeParams', 'MyService', 'MyOtherService', function($controller, $scope, $routeParams, MyService, MyOtherService) {

    $controller('BaseController', {$scope: $scope});
    
    // $scope now has mySharedLogic 
}]);

Hope it helps. I know it's been a while, so I hope it might help some other searching souls ;)

Cheers,
Itamar

Vibhu Singhal

unread,
Dec 13, 2013, 4:45:44 AM12/13/13
to ang...@googlegroups.com, mi...@hevery.com
helped me :), thanks

Shunsuke Hakamata

unread,
Jan 22, 2014, 5:57:23 AM1/22/14
to ang...@googlegroups.com
Hi, 

I'm trying to inherit scope and this property from parent controller.

This fiddle show my example.


Shunsuke Hakamata.


2012年3月30日金曜日 15時51分11秒 UTC+9 Adam Webber:
Reply all
Reply to author
Forward
0 new messages