Inheritance of Custom Services
in Angular 1.x
Pavel Bosin: pavel@bosin.net
How to better implement
common functionality in multiple AngularJS services
Multiple pages need similar, but different services:
Invoices
Orders
Tickets



Use in Controllers
angular.module('demoApp').controller('InvoiceCtrl',
['$scope', 'Invoices', function ($scope, Invoices) {
Invoices.getFilteredList().then(function (response) {
// set invoices in the table data source
});
}]);
Invoices Controller loads filtered list of invoices
Tickets Controller loads filtered list of tickets
Orders Controller loads filtered list of orders
... and each has some specific differences from others
Common service functionality
{
getObject: function (id) {...},
getList: function () {...},
getFilteredList: function () {...},
getFilters: function () {...},
getFilter: function () {...},
getColumns: function () {...},
getPagination: function () {...}
}tl;dr
Create a function that returns a simple object with the common methods. Call this function while instantiating a service.
Extend the result with object.create().
Add more specific methods.
Wrap the result as Angular service using factory pattern.
Shall we look at details?
- Why not just have independent services?
- Keep your code DRY.
- Why not just use composition?
- Because composition with services as singletons is tricky (we will have an example)
- Why not use inheritance of Controllers instead?
- Controllers should be lean; They usually rely on scope hierarchy and not on inheritance
Any alternatives to services inheritance?
Base Service with Dependency
angular.module('demoApp').factory('BaseService',
['Restangular', function (Restangular) {
var BaseService = {
init: function (config) {...}
getObject: function (id) {...},
getList: function () {...},
getFilteredList: function () {...},
// ... see the slide with common methods
};
return BaseService;
}]);
Child Services
angular.module('demoApp').factory('Invoices',
['Restangular', 'BaseService', function (Restangular, BaseService) {
// specific config: column definitions, filters, api url, etc.
var config = {...},
BaseService.init(config);
var thisService = {
// parent methods
getObject: function (id) {
return BaseService.getObject(id);
},
getFilteredList: function () {
return BaseService.getFilteredList();
},
// additional invoice specific functions
getSubList: function () {...}
};
return thisService;
}]);
Tickets and Orders services are very similar.
Using composition here, we have to implement parent methods as call-through.
Need to improve:
- repeated call-through code in child services
- init data stays in the singleton base service and is broken if more than one child is used at the same time
- use stateless base service, but a lot of data is passed in for every method call :(
- make base service non-signleton!
Non-singleton Base Service
angular.module('demoApp').BaseService = function (Restangular) {
return {
// initialize this base service with data
init: function (config) {
//...
},
// get configuration data
getColumns: function () { return config.columns; },
getFilters: function () { return config.listFilters; },
// get single object by id; returns a promise
getObject: function (id) {
//...
},
// get collection of objects; returns a promise
getFilteredList: function (filter) {
//...
}
};
};
Simple Base Service Usage
angular.module('demoApp').factory('Invoices',
['Restangular', function (Restangular) {
var config = {...}; // specific data
var baseService = angular.module('demoApp').BaseService(Restangular);
var thisService = Object.create(baseService);
thisService.init(config);
// additional invoice specific functions
thisService.getSubList = function () {...};
return thisService;
}]);Questions?
These slides: bit.ly/1zKvecS
Inheritance of Angular Services
By pbosin
Inheritance of Angular Services
- 1,048