Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML

Controller Inheritance in angularjs and How to Avoid Injection of $scope in Controller

4.57/5 (5 votes)
26 Dec 2014CPOL2 min read 45.5K  
This small tip shows how to achieve the controller inheritance in angularjs and also how to avoid injection of $scope in controller.

Introduction

There are scenarios that occur when we need to use all fields/methods of one of the already defined controllers in a new controller and also define our own methods.
We can also override the methods of parent controller and provide our own implementation just like inheritance.

We are also going to see how to avoid $scope injection in controller and avoid to fire respective associated watchers function which results in performance gain.

Using the Code

First, we created our first controller.

JavaScript
 //Defining app for our demo
  var app = angular.module('inheritanceDemo', []);
//Defining controller which would be parent controller
  app.controller('MainCtrl', function() {
//these are the two fields we are declaring in parent controller
  this.dad = 'Dad';
  this.mom = 'Mom';
//we have declared this method also in parent controller
  this.methodclick=function(){
    alert('I am Dad/Mom');
  }
}); 

Here, we have not injected $scope in our controller. Instead of that, we are using "this" object to bind fields and methods for the respective controller.
Yes! It will also do the same job as $scope does and also follow the two way data binding feature. That also, we are going to see ...
While crating the child controller, we will have to use $controller service.
We will need to inject $controller service to instantiate a controller inside child controller.
$controller service is responsible for instantiating controllers.

JavaScript
 app.controller('ChildCtrl', function($controller) {
  var ChildCtrl=this;
//created the instance of parent controller
  ChildCtrl.child = $controller('MainCtrl',{});
//Defined our own field for child controller
  ChildCtrl.child.Name="Puppy"
  /*ChildCtrl.child.methodclick=function(){
     alert('I am their child');
    
  }
  ChildCtrl.child.methodclick1=function(){
     alert('We are separate');
      ChildCtrl.child.Name="We r free";
  }*/
});

Here, I have created the child controller and initialised the ChildCtrl which will hold the reference of "this" object.
So now, the parent controller instance is assigned to child controller using $controller.

C#
ChildCtrl.child = $controller('MainCtrl',{});

Here, child is property defined on ChildCtrl which is a reference of "this" object.
New field "Name" is also defined on this child property which would be specific for ChildCtrl only.
Forget about the methodclick and methodclick1 methods for now. So those are commented now.
Below is the code snippet for HTML. Here, we have used controller as alias.

HTML
   <div style="border:1px;solid;border-color:Red;" 
ng-controller="MainCtrl as parent">
    <p>Hello {{parent.dad}}!</p>
    <p>Hello {{parent.mom}}!</p>
    <span ng-click=parent.methodclick()>Parent Click </span>
    </div>
    <div ng-controller="ChildCtrl as Children">
    <p>Hello {{Children.child.dad}}!</p>
     <p>Hello {{Children.child.mom}}!</p>
       <span ng-click=Children.child.methodclick()>Child Click </span>

Here, you can observe that child controller has inherited all fields and methods from its parent controller.
If you run the code and click on child click span parent method will call.
You can override it by your own implementation.
Just uncomment the method methodclick in child controller and run code again. Now, child method will call on click of Client click method.
If you want to test two way data binding for "this" object which we have used, just add the below HTML in your HTML code.

HTML
<input ng-model="Children.child.Name" />
       <span >{{Children.child.Name}}</span>

Below is the full code snippet:

JS

JavaScript
var app = angular.module('inheritanceDemo', []);
app.controller('MainCtrl', function() {
  this.dad = 'Dad';
  this.mom = 'Mom';
  this.methodclick=function(){
    alert('I am Parents')
  }
});
app.controller('ChildCtrl', function($controller) {
  var ChildCtrl=this;
  ChildCtrl.child = $controller('MainCtrl',{});
  ChildCtrl.child.Name="Puppy"
  ChildCtrl.child.methodclick=function(){
     alert('I am their child');
    
  }
//you can extend the child controller by declaring your own methods.
  ChildCtrl.child.methodclick1=function(){
     alert('We are separate');
      ChildCtrl.child.Name="We r free";
  }
});

HTML

HTML
<!DOCTYPE html>
<html ng-app="inheritanceDemo">
  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <script>document.write('<base href="' + 
    document.location + '" />');</script>
    <link rel="stylesheet" href="style.css" />
    <script data-require="angular.js@1.3.x" 
    src="https://code.angularjs.org/1.3.6/angular.js" 
    data-semver="1.3.6"></script>
    <script src="app.js"></script>
  </head>
  <body >
  <div style="border:1px;solid;border-color:Red;" 
  ng-controller="MainCtrl as parent">
    <p>Hello {{parent.dad}}!</p>
    <p>Hello {{parent.mom}}!</p>
    <span ng-click=parent.methodclick()>Parent Click </span>
    </div>
    <div ng-controller="ChildCtrl as Children">
    <p>Hello {{Children.child.dad}}!</p>
     <p>Hello {{Children.child.mom}}!</p>
       <span ng-click=Children.child.methodclick()>Child Click </span></br>
       <span ng-click=Children.child.methodclick1()>Separate Child Click </span>
        <input ng-model="Children.child.Name" />
       <span >{{Children.child.Name}}</span>
    </div>
  </body>
</html>

Demo

I have created a demo on plunkr with this code, here is the link to it:

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)