uglycode
uglycode

Reputation: 3092

AngularJS - controller inheritance

I'm using angular route and I have a situation, where two views basically manipulate the same data. Now, the data is provided via factory to both controllers. However, the functionalities are quite the same.

I won’t go into too many details, but creating a service or factory (which is commonly suggested in this situations) does not solve my issues, since the button clicks etc. are basically the same in both views. I'd still have to define the same button clicks twice, except the logic would be in the factory. The only difference between my two views is, that view2 has a few more functionalities than view1, otherwise it’s basically the same.

What I’d need now is some kind of controller inheritance. I found a couple of solutions, but I’m still searching for an optimal and correct solution. I used the angular.extend to clone the scope, but I’m not sure if this is the correct way.

Furthermore, what happens with $scope from view1 when it gets cloned to $scope in view2? Does it get overridden?

Here’s a simple example: http://jsbin.com/fiqeha/1/edit?html,js,output

Upvotes: 1

Views: 1066

Answers (2)

Johnny
Johnny

Reputation: 286

You can implement controller inheritance by declaring the base as a factory and injecting them into your controllers using $injector e.g.

angular.module('app').factory('BaseController', function () {

  var controller= function($scope){

    $scope.value = 0;

    $scope.testFunction = function () {
      $scope.value++;
    }; 

    $scope.overrideFunction = function() {
       $scope.value--;
    }
  }

  return controller;
});

and in the child controller,

angular.module('app').controller('ChildController', function ($scope, 
  $injector, BaseController) {

  //Inherit base controller - first line in controller
  $injector.invoke(BaseController, this, {$scope: $scope});

  $scope.overrideFunction = function () {
     //call base function
     $scope.value = $scope.testFunction() + 2;
  };

});

Upvotes: 4

Davin Tryon
Davin Tryon

Reputation: 67336

Why not use the same controller? You will get two separate instances of the controller, which should be exactly what you want.

Here is a fork of your jsbin.

js:

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

    $scope.name = "John";

    $scope.displayName = function(){
        alert($scope.name);
    };

    $scope.getNameLength = function(){
        alert($scope.name.length);
    };

}]);

html:

<body>
    <b>view1.html</b>
    <div ng-controller="ctrl1">
        <input ng-model="name" />
        <button ng-click="displayName()">Display</button>
    </div>
    <br />
    <br />
    <b>view2.html</b>
    <div ng-controller="ctrl1">
        <input ng-model="name" />
        <button ng-click="displayName()">Display</button>
        <button ng-click="getNameLength()">Length</button>
    </div>
</body>

Upvotes: 0

Related Questions