0

I'm using Angular 1.4.8 and am trying to extend a controller. Both the original controller and the extending controller are extremely similar, but there's a function I want to override in the extending controller.

angular.module('app').controller('ControllerOne', function() {

    var vm = this;

    vm.data = {};

    vm.callSayHello = function() {
        vm.sayHello();
    }

    vm.sayHello = function() {
        console.log('Hello from ControllerOne.');
    }
});

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

    angular.extend(vm, $controller('OrdersAddController', { $scope: $scope }));

    // I do not want to override vm.callSayHello(), so I don't redeclare that function.

    // This is what I want to override.
    vm.sayHello = function() {
        console.log('Hello from ControllerTwo.');

        // Some other extra handling.
    }
}]);

<button type="button" ng-click="ctrl.callSayHello()">Click Me</button>

It looks like I can override the ControllerOne functions in ControllerTwo. But for this particular case, the function I want to override, vm.sayHello(), isn't directly called from an event like a click, but rather it's called by another function, vm.callSayHello().

So what happens is that when vm.callSayHello() is invoked from either ControllerOne or ControllerTwo, that also calls vm.sayHello(), but it always calls the function on ControllerOne despite being redeclared in ControllerTwo.

Hopefully that makes sense. But is there a way to just override that vm.sayHello() function in ControllerTwo?

2 Answers 2

1

you can do it like this:

function mySmth(vm, $scope) {
  // no vm = this
 vm.smth = ...
}

now:

function baseCtrl($scope) {
  var vm = this;
  mySmth(vm, $scope);
}

function etendedCtrl($scope) {
  var vm = this;
  mySmth(vm, $scope);
  vm.smth = ...// something new
}

But this is not fancy and actually nice advice is - just do not extend controllers... If you have common functions - put them to service or to separate controller.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for your answer. I have read that people generally do not recommend extending controllers, but they were so close in functionality that I was hoping there was an acceptable way.
1

You can use javascript inheritance for ur approach,

//controller 1
function ControllerOne() {
  this.data = {};
}

ControllerOne.prototype.callSayHello = function() {
  this.sayHello();
};

ControllerOne.prototype.sayHello = function() {
  console.log('Hello from ControllerOne.');
};

ControllerOne.$inject = [];

//controller 2
function ControllerTwo($scope) {

}

ControllerTwo.prototype = Object.create(ControllerOne.prototype);

ControllerTwo.constructor = ControllerTwo;

ControllerTwo.prototype.sayHello = function() {
  console.log('Hello from ControllerTwo.');
};

ControllerTwo.$inject = ['$scope'];


//angular controller
angular.module('app', [])
  .controller('ControllerOne', ControllerOne)
  .controller('ControllerTwo', ControllerTwo);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
  <div ng-controller="ControllerOne as ctrl">
    <button type="button" ng-click="ctrl.callSayHello()">Click Me (Ctrl 1)</button>
  </div>
  <div ng-controller="ControllerTwo as ctrl">
    <button type="button" ng-click="ctrl.callSayHello()">Click Me (Ctrl 2)</button>
  </div>
</div>

1 Comment

Nice one. I was hoping to see this answer here.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.