Angularjs OrderBy на ng-repeat не работает

Я пытаюсь использовать AngularJS для своего первого проекта (менеджер турниров), а фильтр orderBy на ng-repeat не работает:( Я прочитал все документацию об этом, но нечего делать:/

Итак, у меня есть vars, определенные на $scope следующим образом:

$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,
  },
  [...]
};

Теперь, по моему мнению, я пытаюсь изменить порядок (сначала только с одним элементом заказа), но никогда не работает...

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

Во второй раз, я хочу переупорядочить из 2-х частей информации: count_win и goal_average, если первые равны. Я пытаюсь заменить $scope.order_item таким образом, но если с одним код не работает, он никогда не будет работать с 2...

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

Спасибо всем за чтение и извините за размер сообщения.

Ответ 1

$scope.teams не является массивом (это объект объектов), а фильтр orderBy работает только с массивами. Если вы создадите массив $scope.teams, он будет работать:

$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,
     }
];

Или вы можете добавить специальный фильтр, который работает на объектах, например этот (заимствованный из здесь):

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;
  };
});

И используйте его следующим образом:

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

Обратите внимание, что этот настраиваемый фильтр не будет работать с массивом порядков сортировки, как во второй части вашего вопроса.

Ответ 2

Вам не нужно создавать параметр области для вашего заказа, вы можете прямо сделать это в своей разметке, если вы имеете дело с массивами.

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

С двумя параметрами вы должны просто сделать

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

После более сложного порядка вы можете создать функцию в своей области следующим образом:

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

И просто назовите его

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

Как сказал @Jerrad, ng-repeat работает только с массивами, поэтому вам нужно преобразовать объект команд в массив, чтобы он работал правильно.

Ответ 3

ng-repeat работает только на массивах, а не на объектах JSON. Это уже обсуждалось здесь: Angular - Невозможно выполнить операцию orderby ng-repeat

Вам либо нужно изменить объект JSON на массив, либо преобразовать его на лету. Затем контроллер мог бы выглядеть так:

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';
});

Я создал скрипку здесь с демонстрацией, содержащей ваши данные:

http://jsfiddle.net/c3VVL/