New version Angular 9
Refactoring and inheritance
- Previous
- Next
In this part we will discover how to setup base controllers for the standard operations
and how to build an application in minutes.
The samples can be run with Firefox, in general or by running, into the directory,
- If you have Python 2.x: python -m SimpleHTTPServer 8000
- If you have Python 3.x: python -m http.server 8000
- If you have Perl:
- cpan HTTP::Server::Brick # install dependency
- perl -MHTTP::Server::Brick -e '$s=HTTP::Server::Brick->new(port=>8000); $s->mount("/"=>{path=>"."}); $s->start'
- If you are under windows: "C:\Program Files (x86)\IIS Express\iisexpress.exe" /path:%CD% /port:8000
Download
The source for this part is here: 07_inherit.zip.
The image is roialty free... taken from freedigitalphotos.net, nothing on the UI changes with this step!

Kitten...a-hem Angular Controllers inheritance
Given a controller with a service
myApp.service('myService',[function....]);
myApp.controller('BaseController',['$scope','$http','myService',function($scope,$http,myService){
...
}]);
I can create a controller that inherits all its behaviours, variables etc. But i must add
the dependency from the $controller service.
Note that we pass an object to the base controller, the scope, that must be passed to keep the same
context as the child controller. We don't pass the $http and myService services, since they will
be resolved automatically by Angular dependency injection
myApp.controller('InheritedController',['$scope',function($scope){
$controller('BaseController',{$scope:$scope});
...
}]);
Refactoring...mostly everything
Our aim is to build generic CRUD controllers to avoid rewriting all the boring logic for ever and ever again.
The sgDialogService
First we will use this awesome library for the dialogs derived from the tutorial. Can be founded here
following the installation instruction. We replace all call to modalDialogService to sgDialogService.
The code
Adding the dataService "interface"
We define an "interface" that we will follow with all that is needed to manage our customers. Here we define
- The templates that we will user
- new
- detail
- edit
- The function that given an item will ask if we want to delete an item
- The function that will give us the form titles for
- detail
- edit
- create
- The functions that will give us the API address of the various CRUD operations
- list
- get
- update (or put)
- add
- delete
customers.service('customersDataService', [function() {
this.newTemplate='app/customers/new.html';
this.detailTemplate='app/customers/detail.html';
this.editTemplate='app/customers/edit.html';
this.deleteConfirm=function(item){ return "You want to delete customer n."+item.id+"?";}
this.detailMessage = function(item){return "Customer "+item.id;}
this.editMessage = function(item){return "Editing Customer "+item.id;}
this.createMessage = function(){return "Create Customer";}
this.list=function(){ return "/customers";};
this.get = function(item){ return '/customers/'+item.id;}
this.put = function(item){return '/customers/'+item.id;}
this.add = function(item){return '/customers';}
this.delete=function(item){return '/customers/'+item.id;}
}])
Then we add to all the customers controller a dependency on this service and we replace all the instances of
the given string and replace them. For example the addNew
$scope.addNew = function(){
globalModalService.openModal(
{
template:'app/customers/new.html',
callback: function(){ $scope.loadData();}
})
}
Becomes the following, adding even the call to "loadData" to refresh the list
automatically when adding items. Note the callback result
$scope.addNew = function(){
sgDialogService.openModal(
{
templateUrl:dataService.newTemplate,
callback: function(){ $scope.loadData();}
})
}
Changing data binding
All the references to $scope.customer or $scope.customers will be changed to $scope.data.
At the same time when we iterate on the customers on the list, we will iterate on data, and when
on the detail, edit and new we will use "data" as model.
Adding to the common module.
Now we will create a new "controller.js" under the commons directory and we will move all the controllers
there. The controllers will be created as children of the "commonModule" and their names will be transformed
like CustomersListController in ListController and so on.
The dependency from the customersDataService will become a dependency on a generic "dataService".
Implementing the REAL controllers
We will now add our new controllers into the customers module! For example the following.
Note that
- The only variable passed down directly is the $scope. We must use the same scope for the 2 controllers
- The data service is forced to "customersDataService". Is important the name of the property on the
object passed to the $controller service!!
The same must be done for all the controllers.
customers.controller('CustomersListController',['$scope','$http','globalMessagesService',
'$controller','customersDataService',
function($scope,$http,globalMessagesService,$controller,customersDataService){
$controller('ListController',{
$scope:$scope,
dataService:customersDataService
});
}]);
The callbacks
Since we are creating a library we must add callbacks to the base controller. We define another
"interface". That we add as a dependency to all our base controllers.
commonControllersCallbacks={
postLoadData:function(data),
postGet:function(data),
preSave:function(data),
postSave:function(data),
postGetUpdate:function(data),
preUpdate:function(data),
postUpdate:function(data),
preDelete:function(data),
postDelete:function(data)
}
We define a default service that does nothing (to limit the code to write :P )
common.service('commonControllersCallbacks',[function(){
return {}
}]);
For example the edit controller becomes the following with the commonControllersCallback. (Note the name inside the parameter
is changed for brevity to "callbacks", the important is the "string" name of the parameter)
All the functions are verified for the existence!!
common.controller('EditController',['$scope','$http','$location','$routeParams','globalMessagesService','modalInstance',
'dataService','commonControllersCallbacks',
function($scope,$http,$location,$routeParams,globalMessagesService,modalInstance,dataService,callbacks){
...
$http.get(dataService.get($scope.item)).
success(function(data, status, headers, config) {
...
//HERE IS ADDED THE CALLBACK
if(callbacks.postGetUpdate)callbacks.postGetUpdate($scope.data);
...
var update = function(){
//HERE IS ADDED THE CALLBACK
if(callbacks.preUpdate && !callbacks.preUpdate($scope.data))return;
$http.put(dataService.put($scope.data),$scope.data).
success(function(result, status, headers, config) {
//HERE IS ADDED THE CALLBACK
if(callbacks.postUpdate)callbacks.postUpdate($scope.data);
modalInstance.closeModal();
}).
And to add the callbacks we will simply do the following (if needed!)
customers.controller('CustomerEditController',['$scope','$http','$location','globalMessagesService',
'$controller','modalInstance','customersDataService',
function($scope,$http,$location,globalMessagesService,$controller,modalInstance,customersDataService){
$controller('EditController',{
$scope:$scope,
dataService:customersDataService,
modalInstance:modalInstance,
commonControllersCallbacks:{
postUpdate:function(item){ alert("Item updated!!");}
}
})
}]);