65.9K
CodeProject is changing. Read more.
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.57/5 (5 votes)

Dec 26, 2014

CPOL

2 min read

viewsIcon

45511

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.

 //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.

 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.

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.

   <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.

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

Below is the full code snippet:

JS

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

<!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: