it-swarm.com.ru

Orderby не работает с синтаксисом dict в ng-repeat

Я пытаюсь использовать ng-repeat с синтаксическим стилем словаря и применить порядок к значению ключа.

(key, value) in something | orderBy:'key' 

Кажется, OrderBy не работает, как ожидалось

Пример здесь http://jsfiddle.net/mhXuW/

38
Cameron Singe

Параметры для orderBy должны соответствовать именам свойств в массиве объектов.

Ваши данные должны выглядеть примерно так:

$scope.list2 = [ { id:"2013-01-08T00:00:00", name:'Joe'},
                 { id:"2013-01-09T00:00:00", name:'Sue'}];

Тогда такой фильтр будет работать:

<div ng-repeat="item in list2 | orderBy:'id':true">

Fiddle .

Обратите внимание, что orderBy работает со всем массивом (something в вашем примере кода выше) и возвращает отсортированный массив. orderBy ничего не знает о key и value.

19
Mark Rajcok

это не реализовано. пожалуйста, смотрите здесь:

https://github.com/angular/angular.js/issues/1286

РЕДАКТИРОВАТЬ (27 августа 2013 г.): эта проблема, кажется, решена сейчас.

11
akonsu

Я создал собственный фильтр, чтобы сделать это возможным для списка выбора:

.filter('toDictionaryArray', function () {
    return function (obj) {
        if (!(obj instanceof Object)) return obj;

        var arr = [];
        for (var key in obj) {
            arr.Push({ key: key, value: obj[key] });
        }
        return arr;
    }
})

тогда список выбора ng-options выглядит следующим образом:

<select ng-options="kv.key as kv.value for kv in p.options | toDictionaryArray | orderBy:'value'"></select>
6
Peter Riesz

Вот хорошая работа ( angular-toArrayFilter ):

.filter('toArray', function () {
  return function (obj, addKey) {
    if ( addKey === false ) {
      return Object.keys(obj).map(function(key) {
        return obj[key];
      });
    } else {
      return Object.keys(obj).map(function (key) {
        if(typeof obj[key] == 'object') return Object.defineProperty(obj[key], '$key', {     enumerable: false, value: key});
      });
    }
  };
});
2
joseym

Как говорит Аконсу, функция была запрошена здесь . Тем не менее, я все еще не мог заставить его работать с последней (1.3.0) бета.

В комментариях есть хороший обходной путь похоронен (обратите внимание, что для этого требуется подчеркивание , и вам придется заменить ссылки на 'ключ' на 'значение. $ Ключ' в приведенном выше примере):

[Добавить фильтр]:

app.filter('toArray', function() { return function(obj) {
    if (!(obj instanceof Object)) return obj;
    return _.map(obj, function(val, key) {
        return Object.defineProperty(val, '$key', {__proto__: null, value: key});
    });
}});

Пример разметки:

<div ng-repeat="val in object | toArray | orderBy:'priority' | filter:fieldSearch">
  {{val.$key}} : {{val}} 
</div>

Потенциальные недостатки:

  • Object.defineProperty не будет работать таким образом в IE8 (если вы не Сделаете перечисление $ key перечислимым, это легко изменить). 
  • Если значения вашего свойства не являются объектами, вы не можете установить свойство $ key и это не удается.
  • Он не интегрирован напрямую в orderBy или ngRepeat поэтому синтаксис другой.
2
Dunc

Вместо использования фильтра orderby, который поддерживает только массивы, а не объекты. Вы можете написать свой собственный фильтр, как этот, я взял код у Джастина Клемма http://justinklemm.com/angularjs-filter-ordering-objects-ngrepeat/ и добавил поддержку для указания нескольких полей заказа. Пример фильтра ниже - это фильтрация на основе свойств в значениях, но вы также можете легко изменить ее на фильтрацию на основе ключа.

app.filter('orderObjectBy', function()
{
    return function(items, fields, reverse)
    {
        var filtered = [];
        angular.forEach(items, function(item)
        {
            filtered.Push(item);
        });

        filtered.sort(function (a, b)
        {
            var result = 0;

            for (var i = 0; i < fields.length; ++i)
            {
                if (a[fields[i]] > b[fields[i]])
                {
                    result = 1;
                    break;
                }
                else if (a[fields[i]] < b[fields[i]])
                {
                    result = -1;
                    break;
                }
            }

            return result;
        });

        if (reverse)
        {
            filtered.reverse();
        }

        return filtered;
    };
});

Затем внутри вашей html5-страницы используйте его так, чтобы статистика представляла собой карту/словарь с парами ключ-значение. 

<div class="row" ng-repeat="stat in statistics | orderObjectBy: 'NumTimesPartnered', 'NumTimesOpponent']:true">
    <div class="col col-33">{{stat.Name}}</div>
    <div class="col"><center>{{stat.NumTimesPartnered}}</center></div>
    <div class="col"><center>{{stat.NumTimesOpponent}}</center></div>
</div>
0
Patrick Tan