0

I don't really understand how to inherit controller objects in angular (not using $scope), when we're surrounding them in a IIFE.

So assume we have 2 controller files:

Animal.js

(function() {
    'use strict';
    angular.module('myApp').controller('animalCtrl', function() {
        this.strength = 3;
        this.speed = 3;
});
})();

Beaver.js

(function() {
    'use strict';
    angular.module('myApp').controller('beaverCtrl', function() {
        //How do I inherit the parent controllers stats?
});
})();

How can I inherit from animalCtrl using my beaverCtrl?

user1413969
  • 1,261
  • 2
  • 13
  • 25
  • 1
    possible duplicate of [Can an AngularJS controller inherit from another contoller in the same module?](http://stackoverflow.com/questions/18461263/can-an-angularjs-controller-inherit-from-another-contoller-in-the-same-module) – Shomz Nov 12 '14 at 20:47

2 Answers2

2

The best way to share data on any angularjs site is by using services. In this case I would create a factory that will store strength and speed and share it with beaverCtrl.

angular.module('<yourappname>', [])
  .factory('dataService', function() {
    $scope = this;

    $scope.strength = null;
    $scope.speed = null;

    $scope.setStrength = function(value) {
      $scope.strength = value;
    }

    $scope.setSpeed = function(value) {
      $scope.speed = value;
    }
    return $scope;
})

Then in the controllers you would call the service like this

.controller('animalCtrl', function(dataService) {
  this.strength = 3;
  this.speed = 3;

  dataService.setStrength(this.strength);
  dataService.setSpeed(this.speed);

});

.controller('beaverCtrl', function(dataService) {
  this.strength = dataService.strength;
  this.speed = dataService.speed;
});
Rorschach120
  • 1,200
  • 1
  • 11
  • 18
2

It's important to realize that an AngularJS controller is just a normal javascript "class". The only catch is invoking the base constructor with dependency injection.

// Create some base class.
BaseController = function($scope, $route) {
  // Do some stuff here.
};

// The base class has some behavior.
BaseController.prototype.someMethod = function() { /* do something */ };

// Create some child class.
ChildController = function($scope, $injector) {
  // Invoke the base constructor.
  $injector.invoke(this, BaseController, {$scope: $scope});
};

// Inherit from the base class.
ChildController.prototype = Object.create(BaseController.prototype);

// Add more specific behavior.
ChildController.prototype.someChildMethod = function() { /* do something */ };

Then you can register your controller as

angular.module('myApp').controller('ChildController', ChildController);

Keep in mind that using inheritance like this will be problematic if overused. It should only be used for sharing behavior. Additionally, using composition of different "classes" is generally going to be much more flexible than using inheritance.

From a code organization standpoint, I would also recommend that you declare your controllers in one place (one file per controller) and register them onto modules in another place (one file per module).

Jeremy Elbourn
  • 2,630
  • 1
  • 18
  • 15
  • I'm a bit confused how you can call $injector.invoke(this, BaseController, {$scope: $scope}); If the controllers are in different files with an IIFE surrounding them, then the BaseController isn't visible to the ChildController. I guess this is more of a javascript issue than an angular one, but your response was helpful. – user1413969 Nov 12 '14 at 22:22
  • I omitted the organization parts to keep the example simple. In a real application, you'd want to have some kind of _load-time_ module system. Angular modules deal with _run-time_ dependencies (i.e., configuring the dependency injector and html compiler). – Jeremy Elbourn Nov 12 '14 at 22:27