2014-10-29 15 views
6

Mam powtarzanie iteracji ng nad zestawem obiektów, które wymaga niektórych funkcji do wyodrębnienia wartości, które chcę sortować według.angularjs orderBy z wieloma funkcjami, jak cofać?

Moja ng-repeat wygląda następująco:

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

Co mam problemy z, to chciałbym sortFnOne zostać odwrócona. Są to wyodrębnianie ciągów, do których nie mogę uzyskać dostępu za pomocą prostych atrybutów, ponieważ przeprowadzają konwersję danych, aby utworzyć wartości, które próbuję sortować.

Gdyby to było proste, wiem, że ja po prostu zrobić:

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

Jeśli funkcje te były po prostu powrocie wartości logicznych I może po prostu! zwracaną wartość, aby uzyskać pożądany wynik, ale niektóre z nich zwracają ciągi, a niektóre zwracają daty w formacie RRRR-MM-DD.

+1

Czy rozważałeś po prostu napisanie własnego filtra? W twoim przypadku szkoda, że ​​flaga 'reverse' (tj. Druga argumentacja) oferowała' orderBy' tylko dla całej tablicy. – miqid

+0

I sekunda @miqid dotyczące filtra. Możesz chcieć rzucić okiem na ten link. To może ci pomóc. http://justinklemm.com/angularjs-filter-ordering-objects-ngrepeat/ –

+0

Post plunker lub skrzypce z minimalnym przykładem, to łatwiej jest pomóc –

Odpowiedz

0

Osobiście spotkałem się z tym ograniczeniem ... nie ma możliwości odwrócenia zamówienia złożonego przez funkcję z filtrem orderBy.

O ile wiem, nie ma prostego sposobu na odtworzenie tego rodzaju uporządkowania złożonego z kierunkiem (porządek "A" rosnąco, a następnie "B" malejący) w natywnym API JavaScript.

Array.prototype.sort oferuje podstawowe zamówienie za pomocą funkcji porównania (szczegółowe informacje znajdują się w części MDN docs), ale nie ma możliwości łatwego przełączenia kolejności sortowania (odwrotnie) bez napisania kolejnej funkcji porównania i nie oferuje rozwiązania dla złożonego zamówienia. Potrzebujemy zwartej notacji, aby określić kierunek i priorytet wielu zamówień.

Napisałem tego pomocnika jakiś czas temu, aby pomóc w rozwiązaniu tego problemu.

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

To nie jest filtr kątowy, więc po prostu zapakuj go w metodę kontrolera i wywołaj z szablonu. Lub po prostu zastosuj porządek do swojej tablicy wewnątrz kontrolera.

myślę, że to może być dostosowany do filtra kątowego ...

Runnable Próbka:

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

kątowa pozwala zapewnić funkcję komparatora jako trzeci argument Zamów przez. Ta funkcja komparatora umożliwia określenie własnego zamówienia.

Oto Plunk, który demonstruje dynamiczne sortowanie złożone. Ładuje 100 rekordów z pliku JSON i początkowo sortuje nazwy według nazwiska, a następnie według imienia. Kiedy sortujesz według czegoś innego niż Nazwisko, używa się nazwiska i imienia do zerwania więzi. Mimo że kolejność sortowania w polu podstawowym może zostać odwrócona, przedstawiony przykład nadal sortuje nazwisko i imię w porządku rosnącym.

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

Powyższa funkcja służy do porównania z połączonym Plunk. Uwaga na koniec, że odwrócenie sortowania na polu jest tak proste, jak pomnożenie wyniku przez -1.

Powiązane problemy