2

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! :-)

RavenHursT
  • 2,336
  • 1
  • 25
  • 46
  • 1
    See: http://stackoverflow.com/questions/13471129/angularjs-ng-repeat-finish-event – tymeJV Jan 21 '14 at 23:07
  • Arg... works for initial rendering of the table by ngRepeat.. but not for subsequent table renderings via orderBy... [link](http://jsfiddle.net/Troop4Christ/7GARr/1/) – RavenHursT Jan 21 '14 at 23:34
  • 1
    I'm not familiar with orderBy, but it may be easier in this case to create your own sorting function to call on the object, with a callback to give the functionality you require. – caffeinated.tech Jan 22 '14 at 00:29
  • Thought about that.. but that'll just give me the ability to do something after the array has been sorted.. but that doesn't ensure that the view built on the data in that array has completed rendering yet.. right? Clearly, based on the link that @tymeJV gave, we have a way to fire an event once the initial render of an ng-repeat has completed.. there's gotta be way to do it subsequently upon changes to the referenced array. – RavenHursT Jan 22 '14 at 00:53
  • Ok.. @LcLk just might be on to something here.. maybe I can just write my own sort function (since the orderBy filter doesn't seem to actually sort the array on the parent scope.. grrr), and then place a $watch on that array to do what I need to do once it's sorted... Gonna give it a shot! – RavenHursT Jan 22 '14 at 01:20

1 Answers1

1

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..

RavenHursT
  • 2,336
  • 1
  • 25
  • 46