Aviv Paz Aviv Paz - 2 months ago 13
AngularJS Question

Dynamic orderBy with function call on ng-repeat angularjs

I'm trying to dynamically change ng-repeat order.

I have a list of 2 strings which suppose to order by a property of the objects and one function the is calculate the total engagement of the object.

The controller

/**
* the available filters for the sort
* @type []
*/
$scope.orders = [
{name: "Newest", order: '-created_at'},
{name: "Oldest", order: 'created_at'},
{name: "Most Engaged", order: 'totalEngagement'}
];

$scope.totalEngagement = function (content) {
total = 0;
if (content.likes_count)
total -= content.likes_count;
if (content.comments_count)
total -= content.comments_count;
return total;
};


/**
* Set the chosen order to sort the buzz content by
* @param order - the chosen order
*/
$scope.setOrder = function (order) {
$scope.selectedOrder = order;
};


The view

<div ng-init="setOrder(orders[0])" class="col-sm-6 col-md-4 col-lg-3 mix "
ng-repeat="content in campaign.content | orderBy:selectedOrder.order">


Now, the 2 order by property works fine but the function doesn't fire when i choose the order. If I'm putting instead of the selectedOrder.order, the function name, the order by works fine.

I added a plunker example

http://plnkr.co/edit/YAgiDq0PJyqOO3BqYGyz?p=preview

Answer

The order field of the "Most Engaged" order should be the function itself, not the name of the function. If you pass a string, angular will try to order by the field totalEngagement of your objects, and they don't have such a field.

So, in short, what you need is

$scope.totalEngagement = function (content) {
    total = 0;
    if (content.likes_count)
        total -= content.likes_count;
    if (content.comments_count)
        total -= content.comments_count;
    return total;
};

$scope.orders = [
    {name: "Newest", order: '-created_at'},
    {name: "Oldest", order: 'created_at'},
    {name: "Most Engaged", order: $scope.totalEngagement}
];

Or, since the function need not be in the scope,

$scope.orders = [
    {name: "Newest", order: '-created_at'},
    {name: "Oldest", order: 'created_at'},
    {name: "Most Engaged", order: totalEngagement}
];

function totalEngagement(content) {
    total = 0;
    if (content.likes_count)
        total -= content.likes_count;
    if (content.comments_count)
        total -= content.comments_count;
    return total;
}