What's the recommended way to extend AngularJS controllers?

vladexologija picture vladexologija · May 14, 2013 · Viewed 82.1k times · Source

I have three controllers that are quite similar. I want to have a controller which these three extend and share its functions.

Answer

Enzey picture Enzey · Oct 29, 2013

Perhaps you don't extend a controller but it is possible to extend a controller or make a single controller a mixin of multiple controllers.

module.controller('CtrlImplAdvanced', ['$scope', '$controller', function ($scope, $controller) {
    // Initialize the super class and extend it.
    angular.extend(this, $controller('CtrlImpl', {$scope: $scope}));
    … Additional extensions to create a mixin.
}]);

When the parent controller is created the logic contained within it is also executed. See $controller() for for more information about but only the $scope value needs to be passed. All other values will be injected normally.

@mwarren, your concern is taken care of auto-magically by Angular dependency injection. All you need is to inject $scope, although you could override the other injected values if desired. Take the following example:

(function(angular) {

	var module = angular.module('stackoverflow.example',[]);

	module.controller('simpleController', function($scope, $document) {
		this.getOrigin = function() {
			return $document[0].location.origin;
		};
	});

	module.controller('complexController', function($scope, $controller) {
		angular.extend(this, $controller('simpleController', {$scope: $scope}));
	});

})(angular);
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.15/angular.js"></script>

<div ng-app="stackoverflow.example">
    <div ng-controller="complexController as C">
        <span><b>Origin from Controller:</b> {{C.getOrigin()}}</span>
    </div>
</div>

Although $document is not passed into 'simpleController' when it is created by 'complexController' $document is injected for us.