So upon building this application I have noticed that some of my controllers are almost identical. I like to keep things DRY so I was hoping to figure out a way to make a generic controller that other controllers can inherit from, but I got a little confused by some of the things I found. Here is an example of 2 of my controllers so you can see the similarities:
.controller('CompaniesController', ['$state', '$filter', 'ArrayService', 'CompanyService', 'toastr', 'companies', 'roles', function ($state, $filter, arrayService, service, toastr, companies, roles) {
// Assign this to a variable
var self = this;
// Get our companies
self.companies = companies;
// Our selected companies
self.selected = [];
self.send = {};
self.delete = {};
// Create our page sizes array
self.pageSizes = [10, 20, 50, 100];
// For filtering and sorting the table
self.pageSize = self.pageSizes[0];
self.predicate = 'email';
self.reverse = false
self.filter = '';
// Select method
self.select = function (company) {
// Modify our array
arrayService.modify(self.selected, company);
// If our array is only 1
if (self.selected.length === 1) {
// Get the current selected company
var current = self.selected[0];
// Set our variables
self.canHaveCenters = (current.role === 'Company');
self.requiresConfirmation = (!current.emailConfirmed);
// Else
} else {
// Reset our variables
self.canHaveCenters = false;
self.requiresConfirmation = false;
}
};
// Check to see if the row is selected
self.isSelected = function (company) {
// If our item is in our array, return true
return (arrayService.indexOf(self.selected, company) > -1);
};
// Change to the edit company state
self.edit = function (e, company) {
// Change our state
changeState(e, company, 'saveCompany.edit');
};
// Change to the company centers state
self.centers = function (e, company) {
// Change our state
changeState(e, company, 'saveCompany.centers');
};
// Deletes a company
self.delete = function (e, company) {
// Perform the delete
recursion(e, company, service.delete, self.delete, '{0} has been deleted.', '{0} companies have been deleted.', true);
};
// Private recursion method
var recursion = function (e, company, serviceCall, resultObject, singleMessage, multipleMessage, removeAfterExecution) {
// Stop propagation
e.stopPropagation();
// If we have an index
if (typeof company !== 'undefined') {
// If our delete succeeded
serviceCall(company.id).then(function () {
// If we are to remove
if (removeAfterExecution) {
// Remove the company from our array
self.companies.data.splice(index);
}
// Display a message
toastr.success($filter('stringFormat')(singleMessage, company.email));
});
// Otherwise we have no index
} else {
// Create our counter
var i = 0;
// Create a variable to hold our errors
var errors = [];
// For each selected company
for (i; i < self.selected.length; i++) {
// Get our index
var index = self.selected[i];
// Get the current company
var company = self.companies.data[index];
// If we have a result
serviceCall(company.id).then(function () {
// If we are to remove
if (removeAfterExecution) {
// Remove the company from our array
self.companies.data.splice(index);
}
// If there is an error
}, function (error) {
// Add to our errors array
errors.push(error);
});
}
// If we have some errors
if (errors.length > 0) {
// Set our delete error
self.error = errors.join();
// Otherwise everything worked
} else {
// Display a message
toastr.success($filter('stringFormat')(multipleMessage, i));
}
}
};
// Private state change method
var changeState = function (e, company, state) {
// Stop propagation
e.stopPropagation();
// If we have an index
if (typeof company !== 'undefined') {
// Change state
$state.go(state, { companyId: company.id });
// Otherwise we have no index
} else {
// If we have 1 selected item
if (self.selected.length === 1) {
// Get our index
index = self.selected[0];
// Get our company
var company = self.companies.data[index];
// Change state
$state.go(state, { companyId: company.id });
}
}
}
}]);
and
.controller('UserCentersController', ['$stateParams', 'ArrayService', 'CenterService', 'centers', 'userCenters', function ($stateParams, arrayService, service, centers, userCenters) {
var self = this;
// Get our user Id
var userId = $stateParams.userId;
// Assign our centers
self.centers = centers;
self.userCenters = userCenters;
// Create our page sizes array
self.pageSizes = [10, 20, 50, 100];
// For filtering and sorting the table
self.pageSize = self.pageSizes[0];
self.predicate = 'name';
self.reverse = false;
self.filter = '';
self.selected = [];
// Create a function to check if a center is in an array
self.contains = function (center) {
// Reference our data
var data = self.userCenters.data;
// If we have any data
if (data) {
// Check to see if our center is in the array
return arrayService.indexOfByKey(data, 'id', center.id) > -1 ? true : false;
}
};
// Adds the current center to the user
self.add = function (e, center) {
// Stop propagation
modify(e, center, true);
};
// Removes the current center from the user
self.remove = function (e, center) {
// Stop propagation
modify(e, center, false);
};
// Select method
self.select = function (center) {
// Modify our array
arrayService.modify(self.selected, center);
// Assign our variables
self.canAdd = searchArray(self.userCenters.data, self.selected, false);
self.canRemove = searchArray(self.userCenters.data, self.selected, true);
};
// Check to see if the row is selected
self.isSelected = function (center) {
// If our item is in our array, return true
return (arrayService.indexOf(self.selected, center) > -1);
};
// Private method for checking if the selected items are all of the same state
var searchArray = function (arrayToCheck, arrayToCompare, contains) {
// Loop through the items to check
for (var i = 0; i < arrayToCompare.length; i++) {
// Get our current item
var item = arrayToCompare[i];
// See if our current id exis
var found = arrayService.indexOfByKey(arrayToCheck, 'id', item.id) > -1;
if (found != contains)
return false;
}
return true;
};
// Private method for handling adding / removing or user centers
var modify = function (e, center, adding) {
// Stop propagation
e.stopPropagation();
// If we have an index
if (typeof center !== 'undefined') {
// Create a list
var list = [];
// Push our center into the list
list.push(center);
// Make our call
service.modifyUserCenters(list, userId, adding).then(function () {}, function (error) {
// Display our error
self.error = error;
});
// Push to our user centers if it's not already there
arrayService.modify(self.userCenters.data, center);
}
};
}]);
Now there are obvious differences, but at the same time there are a lot of similarities. As I am not a JavaSript Guru, things like prototypical inheritance don't really mean anything to me.
I saw this question someone else asked:
Creating a generic angularjs listController
and it seems similar to what I want, but then I stumbled upon these 2 methods:
https://www.exratione.com/2013/10/two-approaches-to-angularjs-controller-inheritance/
and that is where I started getting confused. For my case as you can see, I will probably have similar methods calls and will have some shared variables and functions. I have about 5 controllers that are similar in design and I can see that if I solve this, then I will have a few more for creating / editing controllers too.
Can someone give me, a laymen, a helping hand?