Published: March 25 2014

AngularJS - A Better Way to Implement a Base Controller

There's quite a few different ways of implementing a base controller in AngularJS that people have posted about. Some use pure JavaScript prototypal inheritance while others do it with angular services/factories, however the cleanest and simplest way I've found is to use the AngularJS $controller service. 

Here's a cut down example from an application I'm working on at the moment, it contains controllers for adding and editing diary entries, and a base controller containing shared functionality.

AngularJS Base Controller

'use strict';

angular.module('Diary')

// base controller containing common functions for add/edit controllers
.controller('Diary.BaseAddEditController',
    ['$scope', 'DiaryService',
    function ($scope, DiaryService) {
        $scope.diaryEntry = {};

        $scope.saveDiaryEntry = function () {
            DiaryService.SaveDiaryEntry($scope.diaryEntry);
        };

        // add any other shared functionality here.
    }])

.controller('Diary.AddDiaryController',
    ['$scope', '$controller',
    function ($scope, $controller) {
        // instantiate base controller
        $controller('Diary.BaseAddEditController', { $scope: $scope });
    }])

.controller('Diary.EditDiaryController',
    ['$scope', '$routeParams', 'DiaryService', '$controller',
    function ($scope, $routeParams, DiaryService, $controller) {
        // instantiate base controller
        $controller('Diary.BaseAddEditController', { $scope: $scope });

        DiaryService.GetDiaryEntry($routeParams.id).success(function (data) {
            $scope.diaryEntry = data;
        });
    }]);

(See working on plunker at http://plnkr.co/edit/MfwS4w?p=preview)

It works by creating an instance of the base controller and injecting it with the child controller's $scope, making all the methods and properties added to the $scope by the base controller available in the child controller as well as the view. Although not technically inheritance in the 'classical programming' sense, it solves the issue of having duplicate code between controllers and quite elegantly in my opinion.

UPDATE 15 April 2016 - Added the below modified version that uses "controller as vm" syntax.

AngularJS Base Controller with "Controller as" Syntax

'use strict';

angular.module('Diary')
  .controller('Diary.BaseAddEditController', DiaryBaseAddEditController)
  .controller('Diary.AddController', DiaryAddController)
  .controller('Diary.EditController', DiaryEditController);

// Diary.BaseAddEditController
function DiaryBaseAddEditController(vm, DiaryService) {
	vm.diaryEntry = { name: 'default diary entry from Diary.BaseAddEditController' };

	vm.saveDiaryEntry = function () {
		DiaryService.SaveDiaryEntry(vm.diaryEntry);
	};

	// add any other shared functionality here.
}

// Diary.AddController
function DiaryAddController($controller) {
	var vm = this;

	// instantiate base controller
	$controller('Diary.BaseAddEditController', { vm: vm });
}

// Diary.EditController
function DiaryEditController($routeParams, DiaryService, $controller) {
	var vm = this;

	// instantiate base controller
	$controller('Diary.BaseAddEditController', { vm: vm });

	DiaryService.GetDiaryEntry($routeParams.id).success(function (data) {
		vm.diaryEntry = data;
	});
}

(See working on plunker at http://plnkr.co/edit/ZDvbhL?p=preview)

 


Need Some AngularJS Help?

Search fiverr for freelance AngularJS developers.


Follow me for updates

On Twitter or RSS.


When I'm not coding...

Me and Tina are on a motorcycle adventure around Australia.
Come along for the ride!


Comments


Supported by