2015-03-03 3 views
0

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

Я создал пользовательский фильтр, который появляется, чтобы работать, хотя я получаю ошибку:

"Ошибка: [$ rootScope: infdig].! 10 $ дайджеста() итераций достигнутую Прерывание"

Из того, что я читал на других ответах, это часто связано с возвратом другого значения для каждого фильтра. Я проверил, и я возвращаю тот же объект массива ... поэтому я не уверен, что может вызвать его.

.filter('sortOffers', function() { 
     return function(vals, predicate, reverse) { 
      var vals_old = vals; 

      vals.sort(function(a, b) { 
       var sorter = reverse ? 1 : -1; 

       if(predicate === 'seeking') { 
        if(a.data.valueSought > b.data.valueSought) { 
         return sorter; 
        } else if(a.data.valueSought < b.data.valueSought) { 
         return -sorter; 
        } else { 
         return 0; 
        } 
       } 

       if(predicate === 'offering') { 
        if(a.data.valueOffered > b.data.valueOffered) { 
         return sorter; 
        } else if(a.data.valueOffered < b.data.valueOffered) { 
         return -sorter; 
        } else { 
         return 0; 
        } 
       } 
      }); 

      return vals; 
     } 
    }); 

HTML:

 <tr ng-repeat="offer in offers | sortOffers:sortOffersPredicate:sortOffersReverse" ng-hide="hideDueDateSellers && offer.data.offerType === 'seeking_flexibility' || hideFlexibilitySellers && offer.data.offerType === 'seeking_duedate'"> 
      <td>{{ offer.data.valueOffered || '0' }} {{ offer.offeringString }}</td> 
      <td>{{ offer.data.valueSought || '0' }} {{ offer.seekingString }}</td> 
      <td ng-if="offer.data._owner !== currentUser._id"><button class="ui button positive" ng-click="acceptOffer(offer)">Accept Offer</button></td> 
      <td ng-if="offer.data._owner === currentUser._id"><button class="ui button negative" ng-click="cancelOffer(offer)">Cancel Your Offer</button></td> 
     </tr> 
+1

Вы смущены о цели фильтра. Фильтр ** не может ** изменять данные каким-либо образом. Любая модификация данных вызывает дайджест, который заставляет фильтр оцениваться, данные, которые необходимо изменить (снова), дайджест, который нужно запустить (снова), без конца. Фильтр должен использоваться только для ограничения возвращаемых результатов, а не для изменения данных. данные должны быть отсортированы в контроллере до применения любого фильтра. – Claies

+0

так меняет порядок массива, что вызывает проблему? – Melbourne2991

+1

Если это так, то почему существует собственный порядок по фильтру? https://docs.angularjs.org/api/ng/filter/orderBy – Melbourne2991

ответ

3

Итак, проблема здесь основана на том факте, что массив изменяется в пределах фильтра. Тем не менее, есть способ обойти это, как показано в исходном источнике для родного фильтра orderBy.

Сам массив изменяется функцией .sort(), вызывая цикл $digest. Использование .slice() создаст новый массив, который может быть отсортирован, и новый массив может быть возвращен без запуска $digest.

return vals.slice().sort(function(a, b) { 

Немного больше контекста здесь ...

Там нет ничего плохого с возвращением другого массива с той же структурой данных, что и оригинал. На самом деле у вас есть, чтобы вернуть другой массив из оригинала, если вы устраняете предметы. Путаница в том, что вы не можете вернуть массив (оригинал или копию), где были изменены values. используя .slice(), возвращаемый массив оценивается только один раз, чтобы быть результатом .sort(), и исходный массив никогда не менялся.

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

+0

Отлично, что сработало спасибо, я немного смущен, хотя, поскольку я читал в других вопросах, что это была точная причина, по которой вы получили бы такую ​​ошибку (потому что вы должны вернуть тот же массив не новый) – Melbourne2991

+0

я пробовал этот путь , но массив не был отсортирован должным образом. Может быть, потому, что моя уникальная ситуация. я не знаю – saike

1

Скопируйте массив, прежде чем делать вид. Модификация массива в месте, что обжиг $ часы:

 return vals.slice().sort(function(a, b) { 
      var sorter = reverse ? 1 : -1; 

      if(predicate === 'seeking') { 
       if(a.data.valueSought > b.data.valueSought) { 
        return sorter; 
       } else if(a.data.valueSought < b.data.valueSought) { 
        return -sorter; 
       } else { 
        return 0; 
       } 
      } 

      if(predicate === 'offering') { 
       if(a.data.valueOffered > b.data.valueOffered) { 
        return sorter; 
       } else if(a.data.valueOffered < b.data.valueOffered) { 
        return -sorter; 
       } else { 
        return 0; 
       } 
      } 
     }); 

Я считаю, нг-повтор $ часы выражение правая рука (правая) для изменения с помощью $ watchCollection. $ watchCollection не сравнивает массивы по ссылке, но вместо этого ищет различия в длине, а также будет сравнивать элементы массивов по элементам.