3

When I extend a controller in angular, is there any way to call a function on the "superclass" controller from a "subclass" function that overrides it?

For clarity - in Java I'd do:

class Foo {
    void doStuff(){
        //do stuff 
    }
} 

class FooBar extends Foo {
     void doStuff(){
         super.doStuff();
         //do more stuff
     }
}

and I'd like to do the equivalent in angular - something

myApp.controller('FooCtrl', function($scope){

    $scope.doStuff = function(){
         //do stuff
     }
}).controller('FooBarCtrl', function($scope){
   angular.extend(this, $controller('FooCtrl', {$scope: $scope}));

   $scope.doStuff = function(){
          // ??? <- INSERT ANSWER HERE  
         //do more stuff
     }
}
drew moore
  • 31,565
  • 17
  • 75
  • 112
  • 1
    Short answer: yes (see: http://stackoverflow.com/a/19670187/624590 ). Long answer (/opinion): consider mixins or factories as your means of DRYing your code instead of extends/inheritance. – DRobinson May 15 '15 at 01:52
  • But to make your attempt work, stash the old function somewhere before overriding it: `var superDoStuff = $scope.doStuff; $scope.doStuff = function(){ superDoStuff(); /* do more stuff */ };` – DRobinson May 15 '15 at 02:04

2 Answers2

1

I wouldn't recommend this pattern, but as an answer to the question, here is a way to do it:

myApp.controller('FooCtrl', function($scope){

    $scope.doStuff = function(){
         //do stuff
     }
}).controller('FooBarCtrl', function($scope){
   angular.extend(this, $controller('FooCtrl', {$scope: $scope}));
   //extend the scope
   var super = angular.extend({}, $scope);
   $scope.doStuff = function(){
          // ??? <- INSERT ANSWER HERE  
         //do more stuff
         //call the "superclass" methods
         if(super.doStuff){
            super.doStuff();
         }
   }
}

Spitballing, I suppose of you could write a helper service that allowed you to override properties with references to the superclass implementations to make it cleaner. Perhaps by overriding "this". Something like:

$scope.doStuff = $override($scope.doStuff, function() {

    this();  //calls the original doStuff function
});

.factory('$override', function(){

    return function(method, func){
        return function(){
            return func.apply(method, arguments);
        };
    };
});
Joe Enzminger
  • 11,110
  • 3
  • 50
  • 75
0

You can use $parent

so

$scope.$parent.doStuff()
kwangsa
  • 1,701
  • 12
  • 16
  • 3
    Different kind of inheritance. The question is trying to create a controller that has all of the properties of another controller, but can override them with its own (superclass / subclass style), not a controller that's nested in another (as your answer suggests). http://en.wikipedia.org/wiki/Inheritance_%28object-oriented_programming%29 – DRobinson May 15 '15 at 01:54
  • @DRobinson - precisely. – drew moore May 15 '15 at 02:10