35

I'm trying to use AngularJS for my first project (a tournaments manager) and the orderBy filter on ng-repeat doesn't work :( I have read all the documentation about that, but nothing to do :/

So, I have vars defined on $scope like that :

$scope.order_item = "count_win";
$scope.order_reverse = false;
$scope.teams = {
  100 : {
    id: 100,
    name: "XXX",
    count_win: 1,
    count_loose: 2,
    goal_average: 1,
  },
  200 : {
    id: 200,
    name: "XXX",
    count_win: 1,
    count_loose: 2,
    goal_average: 1,
  },
  [...]
};

Now, on my view i'm trying to reorder (first with only one order item) but never work...

<tr ng-repeat="team in teams | orderBy:order_item:order_reverse">
   <td>{{team.name}}</td>
   <td>{{team.count_loose}}</td>
   <td>{{team.goal_average}}</td>
</tr>

The second time, I want to reorder from 2 pieces of information: count_win and goal_average if first are equal.. I try to replace $scope.order_item like that, but if with one the code doesn't work, he'll never work with 2...

$scope.order_item = ['count_win','goal_average'];

Thank you all for reading and sorry for the post size.

JSK NS
  • 3,346
  • 2
  • 25
  • 42
Arthur
  • 4,870
  • 3
  • 32
  • 57
  • possible duplicate of [Angular - Can't make ng-repeat orderBy work](http://stackoverflow.com/questions/19387552/angular-cant-make-ng-repeat-orderby-work) – Blackhole May 28 '14 at 19:42

3 Answers3

58

$scope.teams isn't an array (it's an object of objects), and the orderBy filter only works with arrays. If you make $scope.teams an array, it will work:

$scope.teams = [
    {
      id: 100,
      name: "team1",
      count_win: 3,
      count_loose: 2,
      goal_average: 2,
    },
    {
      id: 200,
      name: "team2",
      count_win: 3,
      count_loose: 2,
      goal_average: 1,
    },        
    {
      id: 300,
      name: "team3",
      count_win: 1,
      count_loose: 2,
      goal_average: 1,
     }
];

Or, you can add a special filter that works on objects, like this (borrowed from here):

app.filter('orderObjectBy', function() {
  return function(items, field, reverse) {
    var filtered = [];
    angular.forEach(items, function(item) {
      filtered.push(item);
    });
    filtered.sort(function (a, b) {
      return (a[field] > b[field] ? 1 : -1);
    });
    if(reverse) filtered.reverse();
    return filtered;
  };
});

And use it like this:

<tr ng-repeat="team in teams | orderObjectBy:order_item:order_reverse">

Note that this custom filter will not work with an array of sort orders as in the second part of your question.

JSK NS
  • 3,346
  • 2
  • 25
  • 42
Jerrad
  • 5,240
  • 1
  • 18
  • 23
  • I have try to add the filter like that : angular.module('orderObjectBy', []).filter('orderObjectBy', function() { *** }); and angular.module('poolApp', ['poolApp.controllers', 'poolApp.services', 'orderObjectBy']); but don't work :/ angular.mo – Arthur May 28 '14 at 20:03
  • Here's a plunker showing it working: http://plnkr.co/edit/Ml1oLWnqPG72OokYNjb2?p=preview If that doesn't help, I would need to see your code. – Jerrad May 28 '14 at 20:03
  • They are lots of useless code but you maybe understand the problem : http://jsfiddle.net/2u895/ – Arthur May 28 '14 at 20:08
  • Funny how you can ng-repeat it but can't use an order by filter on it. Hope Angular gets more consistent in situations like this. If you can repeat it I'd expect to be able to filter it. – wowo_999 Oct 10 '14 at 02:39
11

You don't have to create a scope parameter for your orderBy, you can directly do this in your markup if you are dealing with arrays.

<tr ng-repeat="team in teams | orderBy:count_win:false">

With two parameters, you should just do

<tr ng-repeat="team in teams | orderBy:['count_win','goal_average']">

After for a more complex order, you could create a function in your scope like so :

$scope.customOrder = function (team) {
    //custom
}

And just call it like

<tr ng-repeat="team in teams | orderBy:customOrder">

Like @Jerrad said, ng-repeat only works with arrays, so you need to convert your teams object into an array to get it work properly.

ryanyuyu
  • 6,366
  • 10
  • 48
  • 53
Preview
  • 35,317
  • 10
  • 92
  • 112
8

ng-repeat works only on arrays, not on JSON objects. This was already discussed here: Angular - Can't make ng-repeat orderBy work

You either have to change the JSON object to an Array, or to convert it on the fly. The controller could then look like this:

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

app.controller('Ctrl', function ($scope) {

    $scope.teams = [
        {
            id: 100,
            name: "A Team",
            count_win: 1,
            count_loose: 2,
            goal_average: 1
        },
        {
            id: 200,
            name: "C Team",
            count_win: 2,
            count_loose: 3,
            goal_average: 4
        },
        {
            id: 300,
            name: "B Team",
            count_win: 4,
            count_loose: 1,
            goal_average: 8
        }
    ];
    $scope.predicate = 'name';
});

I created a fiddle here with a demo containing your data:

http://jsfiddle.net/c3VVL/

Community
  • 1
  • 1
meberhard
  • 1,797
  • 1
  • 19
  • 24