Search code examples
javascriptangularjsangularjs-scopeangularjs-controllercode-reuse

Combining common function in controllers AngularJS


I am working with the project. I am using pagination, checkAll, deleteAll like functionalities that are common between all controllers. I wish to move the code to factory or service so can be utilize to all controllers. I tried but not clear with perfection. I want hint. I know to create factory or service, and how to intefrate it controller but bit confuse with logic of moving similar code.

I give example that I use to write in all controller, Logic for Sorting and pagination as well.

$scope.bigCurrentPage = 1;
$scope.editIndex = "";

var sortKey = "name";
var sortDirection = "ASC";
$scope.filterObj = {order: [sortKey + " " + sortDirection], limit: CONFIG.limit, offset: 0};
$scope.filterObj.offset = ($scope.bigCurrentPage - 1) * CONFIG.limit;

$scope.sortList = function (inputSort) {
    if (sortKey === inputSort) {
        sortDirection = (sortDirection === "ASC") ? "DESC" : "ASC";
    } else {
        sortKey = inputSort;
    }
    $scope.filterObj.order = [sortKey + " " + sortDirection];
    $scope.pageChanged();
}


$scope.getSongs = function () {
    $scope.filterObj.offset = ($scope.bigCurrentPage - 1) * CONFIG.limit;
    Song.find({filter: $scope.filterObj})
            .$promise
            .then(function (data) {
                $scope.items = data;
                $scope.maxSize = 5;
                $scope.size = $scope.filterObj.limit;
                $scope.countingIndex = ($scope.bigCurrentPage - 1) * $scope.filterObj.limit; //Its idea to implement counting. Variable is not part of pagination..////     
            });
};


$scope.pageChanged = function () {
    $scope.getSongs();
};

$scope.pageChanged();

This way, suppose I am doing this for Albums and I would change sortKey as 'id', Will use services with 'Album.find', would change 'filter' object and I am done, but fact is I am using common code in all controllers. How would I write it in better way.


Solution

  • You do have lots of properties which are very hard to maintain in service, so I'd suggest that you should use controller rather than service,(Or put reusable variable in service that would make more code sense). Below is created controller can be inject-able in any other controller using $controller dependency.

    Common Controller

    app.controller('commonCtrl', function($scope) {
        $scope.bigCurrentPage = 1;
        $scope.editIndex = "";
    
        var sortKey = "name";
        var sortDirection = "ASC";
        $scope.filterObj = {
            order: [sortKey + " " + sortDirection],
            limit: CONFIG.limit,
            offset: 0
        };
        $scope.filterObj.offset = ($scope.bigCurrentPage - 1) * CONFIG.limit;
    
        $scope.sortList = function(inputSort) {
            if (sortKey === inputSort) {
                sortDirection = (sortDirection === "ASC") ? "DESC" : "ASC";
            } else {
                sortKey = inputSort;
            }
            $scope.filterObj.order = [sortKey + " " + sortDirection];
            $scope.pageChanged();
        }
    
        $scope.getSongs = function() {
            $scope.filterObj.offset = ($scope.bigCurrentPage - 1) * CONFIG.limit;
            Song.find({
                    filter: $scope.filterObj
                })
                .$promise
                .then(function(data) {
                    $scope.items = data;
                    $scope.maxSize = 5;
                    $scope.size = $scope.filterObj.limit;
                    $scope.countingIndex = ($scope.bigCurrentPage - 1) * $scope.filterObj.limit; //Its idea to implement counting. Variable is not part of pagination..////     
                });
        };
    
        $scope.pageChanged = function() {
            $scope.getSongs();
        };
    
        $scope.pageChanged();
    });
    

    You could inject this created commonCtrl to any other controller using $controller dependency, commonCtrl shares it scope to the controller where it gets injected. But changes done from controllerA in commonCtrl would not be available in controllerB because commonCtrl gave copy of its scope to the controller who inject it.

    Controller A

    app.controller('controllerA', function($scope, $controller){
       $controller('commonCtrl', {$scope: $scope}); //inject commonCtrl scope to current scope
       //common scope will be available from here
    }) 
    

    NOTE

    If you want changes to be reflected in other controller you could use service with this controller which would share common properties to different controllers.