2014-10-29 5 views
6

У меня есть повторение ng-повторения по набору объектов, требующим некоторых функций для извлечения значений, которые я хочу сортировать.angularjs orderBy с несколькими функциями, как отменить?

Мой нг-повтор выглядит следующим образом:

ng-repeat="row in rows | orderBy: [sortFnOne, sortFnTwo, ...]" 

Что у меня возникли проблемы с, как я хотел бы sortFnOne быть отменено. Это извлечение строк, к которым я не могу получить доступ, используя простые атрибуты, поскольку он делает некоторое преобразование данных для создания этих значений, которые я пытаюсь сортировать.

Если бы это было просто, я знаю, что я бы просто сделать:

ng-repeat="row in rows | orderBy: ['-id', 'name', '-status', ...]" 

Если эти функции были только возвращение булевой я только мог! возвращаемое значение, чтобы получить результат, который я хотел, но некоторые из них возвращают строки, а некоторые возвращают даты в формате YYYY-MM-DD.

+1

Вы считали, что вместо этого вы просто написали пользовательский фильтр? В вашем случае стыдно, что флаг 'reverse' (т. Е. Второй аргумент), предлагаемый' orderBy', применяется только ко всему массиву. – miqid

+0

I второй @miqid относительно фильтра. Возможно, вам стоит взглянуть на эту ссылку. Это может вам помочь. http://justinklemm.com/angularjs-filter-ordering-objects-ngrepeat/ –

+0

Опубликовать плункер или скрипку с минимальным примером, тогда легче помочь –

ответ

0

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

Насколько я могу судить, нет простого способа воспроизвести этот тип составного заказа с направлением (порядок от «А» по ​​возрастанию, а по убыванию «В») в родном JavaScript API.

Array.prototype.sort предлагает базовый заказ через функцию сравнения (см. MDN docs). Нам нужна компактная нотация, указывающая направление и приоритет нескольких порядков.

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

var orderByAgeThenName = new OrderByBuilder().asc(getAge).asc(getName).build(); 
    var friendsByAgeThenName = orderByAgeThenName(friends); 

    var orderByNameThenAge = new OrderByBuilder().desc(getName).asc(getAge).build(); 
    var friendsByNameThenAge = orderByNameThenAge(friends); 

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

Я думаю, это может быть адаптирован к угловому фильтру ...

Runnable Пример:

angular.module('orderByExample', []) 
 
.controller('ExampleController', ['$scope', function($scope) { 
 
    var friends = 
 
    [{name:'Jon', phone:'555-1212', age:10}, 
 
    {name:'Zach', phone:'555-2276', age:7},      
 
    {name:'Zach', phone:'555-9876', age:19}, 
 
    {name:'Zach', phone:'555-9276', age:13},   
 
    {name:'Mike', phone:'555-4321', age:21}, 
 
    {name:'Adam', phone:'555-5678', age:35}, 
 
    {name:'Julie', phone:'555-8765', age:29}]; 
 

 
    function getName(f){ 
 
    return f.name; 
 
    } 
 

 
    function getAge(f){ 
 
    return f.age; 
 
    } 
 
    
 
    var orderByName  = new OrderByBuilder().desc(getName).build(); 
 
    var orderByNameAndAge = new OrderByBuilder().desc(getName).asc(getAge).build(); 
 

 
    $scope.friendLists = [ 
 
    {label:'Not Ordered', friends: friends}, 
 
    {label:'Name DESC', friends: orderByName(friends)}, 
 
    {label:'Name DESC, Age ASC', friends: orderByNameAndAge(friends)} 
 
    ]; 
 
    
 
}]); 
 

 

 

 

 
function OrderByBuilder(orderings){ 
 
    var _orderings = []; 
 

 
    return { 
 
    asc: function(fn){ 
 
     addOrdering(true,fn); 
 
     return this; 
 
    }, 
 
    desc: function(fn){ 
 
     addOrdering(false,fn); 
 
     return this; 
 
    }, 
 
    build: build 
 
    }; 
 

 
    function addOrdering(asc,fn){ 
 
    _orderings.push({ 
 
     getterFn: fn, 
 
     asc: asc 
 
    }); 
 
    return this; 
 
    } 
 

 
    function build(){ 
 
    var compare = _orderings.reverse().reduce(function(nextComparer, ordering){ 
 
     return getComparerFn(ordering, nextComparer); 
 
    },null); 
 

 
    return function(xs){ 
 
     return xs.slice().sort(compare); 
 
    }; 
 
    } 
 

 
    // a comparerFn has the following signature: 
 
    // \t \t function(a: obj, b: obj): int 
 

 
    function getComparerFn(ordering, nextComparer){ 
 
    var next = nextComparer || function(a,b){ return 0; }; 
 
    var getVal = ordering.getterFn; 
 

 
    return function(a,b){ 
 
     var aVal = getVal(a); 
 
     var bVal = getVal(b); 
 
     if(aVal < bVal){ return ordering.asc ? -1 : 1; } 
 
     if(aVal > bVal){ return ordering.asc ? 1 : -1; } 
 
     return next(a,b); 
 
    }; 
 
    } 
 
}
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.0-beta.6/angular.min.js"></script> 
 
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css"> 
 

 
<div ng-app="orderByExample"> 
 
    <div ng-controller="ExampleController"> 
 
    <div class="row"> 
 
     <div ng-repeat="friendList in friendLists" class="col-sm-4"> 
 
     <h4>{{friendList.label}}</h4> 
 
     
 
     <table class="table table-bordered table-condensed"> 
 
      <tr> 
 
      <th>Name</th> 
 
      <th>Phone Number</th> 
 
      <th>Age</th> 
 
      </tr> 
 
      <tr ng-repeat="friend in friendList.friends"> 
 
      <td>{{friend.name}}</td> 
 
      <td>{{friend.phone}}</td> 
 
      <td>{{friend.age}}</td> 
 
      </tr> 
 
     </table> 
 
     </div> 
 
    </div> 
 
    </div> 
 
</div>

0

Угловые позволяет обеспечить функцию компаратора в качестве третьего аргумента Сортировать по. Эта функция компаратора дает вам право указывать собственный заказ.

Вот Plunk, который демонстрирует динамическую сложную сортировку. Он загружает 100 записей из файла JSON и первоначально сортирует имена сначала по имени, затем по имени. Когда вы сортируете что-то другое, кроме Last Name, оно использует Last Name и First Name для разрыва связей. Однако, хотя порядок сортировки в основном поле может быть отменен, продемонстрированный пример будет по-прежнему сортировать имя и имя в порядке возрастания.

$scope.compareData = function(left, right) { 
    function compareValues(valueLeft, valueRight) { 
    var valueReturn; 
    if (!isNaN(parseInt(valueLeft)) && !isNaN(parseInt(valueRight))) { 
     valueReturn = 
     ((valueLeft * 1) < (valueRight * 1) 
     ? -1 
     : ((valueLeft * 1) > (valueRight * 1) ? 1 : 0)); 
    } else { 
     valueReturn = valueLeft.toString().localeCompare(valueRight.toString()); 
    } 
    return valueReturn; 
    } 
    var dataReturn = 0; 
    if (typeof right === "undefined") { 
    dataReturn = 1; 
    } else if (typeof left === "undefined") { 
    dataReturn = -1; 
    } else { 
    var valuesLeft = left.value.split(","); 
    var valuesRight = right.value.split(","); 
    for (var i = 0; (i < valuesLeft.length) && (dataReturn === 0); ++i) { 
     dataReturn = compareValues(valuesLeft[i], valuesRight[i]); 
     dataReturn *= ($scope.sortReverse && (i > 0)) ? -1 : 1; 
    } 
    } 
    return dataReturn; 
} 

Вышеупомянутая функция используется для компаратора в связанном Plunk. Обратите внимание, в конце концов, что изменение типа сортировки на поле так же просто, как умножение результата на -1.

Смежные вопросы