Search code examples
javascriptangularjsangularjs-ng-repeatangularjs-orderby

How do I create a callback for ng-repeat orderBy?


Looking for a way to get AngularJS'a ng-repeat orderBy filter to do a callback once it's done rendering...

Markup:

    <div ng-controller="MyCtrl">
    <table>
        <thead>
            <tr>
                <th ng-click="sort('name')">Name:</th>
                <th ng-click="sort('age')">Age:</th>
            </tr>
        </thead>
        <tbody>
            <tr ng-repeat="item in items | orderBy:sortColumn:reverseSort">
                <td>{{item.name}}</td>
                <td>{{item.age}}</td>
            </tr>
        </tbody>
    </table>
</div>

JS:

var myApp = angular.module('myApp', []);

function MyCtrl($scope) {
    $scope.items = [{
        "name": "John",
            "age": 25
    }, {
        "name": "Amy",
            "age": 75
    }, {
        "name": "Sarah",
            "age": 12
    }, {
        "name": "Matt",
            "age": 55
    }, {
        "name": "Xaviour",
            "age": 2
    }];

    $scope.sortColumn = 'name';
    $scope.reverseSort = false;

    $scope.sort = function (column) {
        $scope.sortColumn = column;
        $scope.reverseSort = !$scope.reverseSort;
    };

    $scope.sortRenderFinished = function(){
        console.log('Done Rendering!');
        //Do something
    };
}

JSfiddle

As you can see.. I'd like to see something like $scope.sortRenderFinished() fire once the orderBy filter is done executing and changing the order of the table rows.

Any help would be MUCH appreciated! :-)


Solution

  • As usual I was over-thinking the problem..

    Just needed to create a custom sort function and manage the array manually instead of relying on the orderBy filter in the ng-repeat directive:

    var myApp = angular.module('myApp', []);

    function MyCtrl($scope, $filter) {
        $scope.items = [{
            "name": "John",
                "age": 25
        }, {
            "name": "Amy",
                "age": 75
        }, {
            "name": "Sarah",
                "age": 12,
        }, {
            "name": "Matt",
                "age": 55
        }, {
            "name": "Xaviour",
                "age": 2
        }];
    
    
    
        $scope.addChild = function () {
            var
            matt = $scope.items[findIndexByKeyValue($scope.items, 'name', 'Matt')],
                savannah = {
                    "name": "Savannah",
                        "age": 2,
                        "parent": matt
                };
    
            console.log('matt');
            console.log(matt);
    
            $scope.items.splice($scope.items.indexOf(matt) + 1, 0, savannah);
            matt.child = savannah;
            $scope.matt = matt;
            $scope.savannah = savannah;
        };
    
        var findIndexByKeyValue = function (obj, key, value) {
            for (var i = 0; i < obj.length; i++) {
                if (obj[i][key] == value) {
                    return i;
                }
            }
            return null;
        };
    
    
        $scope.sortColumnExp = '';
    
        $scope.sort = function (column) {
            $scope.sortColumnExp = ($scope.sortColumnExp.indexOf('-') == 0) ? column : '-' + column;
            console.log($scope.sortColumnExp);
            if ($scope.savannah) {
                $scope.items.splice($scope.items.indexOf($scope.savannah), 1);
            }
            $scope.items = $filter('orderBy')($scope.items, $scope.sortColumnExp);
            if ($scope.savannah) {
                $scope.items.splice($scope.items.indexOf($scope.savannah.parent) + 1, 0, $scope.savannah);
            }
        };
    
    }
    

    Working JSFiddle for what I was trying to do... Thanks to @LcLk for the breadcrumb above..