Özelliğe göre AngularJS sıralama


93

Yapmaya çalıştığım şey, bazı verileri özelliğe göre sıralamak. İşte çalışmam gereken bir örnek ama işe yaramıyor.

HTML bölümü:

<div ng-app='myApp'>
    <div ng-controller="controller">
    <ul>
        <li ng-repeat="(key, value) in testData | orderBy:'value.order'">
            {{value.order}}. {{key}} -> {{value.name}}
        </li>
    </ul>
    </div>
</div>

JS bölümü:

var myApp = angular.module('myApp', []);

myApp.controller('controller', ['$scope', function ($scope) {

    $scope.testData = {
        C: {name:"CData", order: 1},
        B: {name:"BData", order: 2},
        A: {name:"AData", order: 3},
    }

}]);

Ve sonuç:

  1. A -> AData
  2. B -> BData
  3. C -> CDveri

... IMHO şöyle görünmeli:

  1. C -> CDveri
  2. B -> BData
  3. A -> AData

Bir şeyi özledim mi ( JSFiddle üzerinde denemeye hazır )?

Yanıtlar:


148

AngularJS'nin orderBy filtresi yalnızca dizileri destekler - nesne içermez. Bu yüzden, sıralamayı sizin için yapan kendi küçük bir filtre yazmanız gerekir.

Veya ele aldığınız verilerin formatını değiştirin (üzerinde bir etkiniz varsa). Nesneleri içeren bir dizi, yerel orderBy filtresine göre sıralanabilir.

İşte AngularJS için orderObjectBy filtrem :

app.filter('orderObjectBy', function(){
 return function(input, attribute) {
    if (!angular.isObject(input)) return input;

    var array = [];
    for(var objectKey in input) {
        array.push(input[objectKey]);
    }

    array.sort(function(a, b){
        a = parseInt(a[attribute]);
        b = parseInt(b[attribute]);
        return a - b;
    });
    return array;
 }
});

Görünümünüzdeki kullanım:

<div class="item" ng-repeat="item in items | orderObjectBy:'position'">
    //...
</div>

Bu örnekte nesne bir konum özniteliğine ihtiyaç duyar, ancak nesnelerde (bir tam sayı içeren) herhangi bir özniteliği yalnızca görünümdeki tanıma göre kullanma esnekliğine sahipsiniz.

Örnek JSON:

{
    "123": {"name": "Test B", "position": "2"},
    "456": {"name": "Test A", "position": "1"}
}

İşte size kullanımı gösteren bir keman: http://jsfiddle.net/4tkj8/1/


1
Bu harika. Asc / desc sıralama seçeneğini ekledim: app.filter ('orderObjectBy', function () {return function (input, attribute, direction) {if (! Angular.isObject (input)) return input; var dizi = [] ; for (var objectKey in input) {array.push (input [objectKey]);} array.sort (function (a, b) {a = parseInt (a [attribute]); b = parseInt (b [attribute]) ; dönüş yönü == 'artan'? a - b: b - a;}); dönüş dizisi;}}); HTML'de: <tr ng-tekrar = "val in list | orderObjectBy: 'prop': 'asc'">
Jazzy

@Armin ya bu dizi gibi bir nesne ise? yani{1:'Example 1', 2:'Example 2', 3:'Example 3', ...}
Eugene

8
Harika cevap AMA bu şekilde nesnenin anahtarını kaybettik. Korumak için, filtrede yeni dizi satırları oluşturarak ekleyin, örneğin for(var objectKey in input) { input[objectKey]['_key'] = objectKey; array.push(input[objectKey]); }Kullanabileceğimiz gibi<div ng-repeat="value in object | orderObjectBy:'order'" ng-init="key = value['_key']">
Nicolas Janel

7
O angularjs belirterek It değerinde yapar desteği şimdi nesneler dizisi bir özelliğe göre sıralama: ... | orderBy: 'name'.
Wildhoney

2
@Wildhoney Bu soru, nesneleri içeren dizilerle değil, anahtarlarla nesnelerin sıralanmasıyla ilgilidir.
Armin

31

Oldukça kolay, sadece böyle yap

$scope.props = [{order:"1"},{order:"5"},{order:"2"}]

ng-repeat="prop in props | orderBy:'order'"

33
Bu, ilişkisel diziler için çalışmaz, soru da budur.
MFB

7

ParseInt () 'in yalnızca Tamsayı değerleri için çalıştığını unutmayın. Dize değerlerini sıralamak için bunu değiştirmelisiniz:

array.sort(function(a, b){
  a = parseInt(a[attribute]);
  b = parseInt(b[attribute]);
  return a - b;
});

Bununla:

array.sort(function(a, b){
  var alc = a[attribute].toLowerCase(),
      blc = b[attribute].toLowerCase();
  return alc > blc ? 1 : alc < blc ? -1 : 0;
});

6

Angular-JS ( https://github.com/angular/angular.js/blob/master/src/ng/filter/orderBy.js ) kodunda görebileceğiniz gibi ng-tekrar nesnelerle çalışmaz. İşte sortFunction ile bir hack.

http://jsfiddle.net/sunnycpp/qaK56/33/

<div ng-app='myApp'>
    <div ng-controller="controller">
    <ul>
        <li ng-repeat="test in testData | orderBy:sortMe()">
            Order = {{test.value.order}} -> Key={{test.key}} Name=:{{test.value.name}}
        </li>
    </ul>
    </div>
</div>

myApp.controller('controller', ['$scope', function ($scope) {

    var testData = {
        a:{name:"CData", order: 2},
        b:{name:"AData", order: 3},
        c:{name:"BData", order: 1}
    };
    $scope.testData = _.map(testData, function(vValue, vKey) {
        return { key:vKey, value:vValue };
    }) ;
    $scope.sortMe = function() {
        return function(object) {
            return object.value.order;
        }
    }
}]);

4

http://docs.angularjs.org/api/ng.filter:orderBy'ye göre , orderBy bir diziyi sıralar. Sizin durumunuzda bir nesneyi iletiyorsunuz, bu nedenle kendi sıralama işlevinizi uygulamanız gerekecek.

veya bir dizi geçirin -

$scope.testData = {
    C: {name:"CData", order: 1},
    B: {name:"BData", order: 2},
    A: {name:"AData", order: 3},
}

http://jsfiddle.net/qaK56/ adresine bir göz atın


Dizilerle çalıştığını biliyorum .. Yani çözüm kendi sıralama fonksiyonumu yazmak mı?
PrimosK

Sizin jsfiddle! = Kodunuz u gönderildi. Buradaki örneğiniz için doğru jsfiddle budur: jsfiddle.net/qaK56/92
mrzmyr

3

Sorununuzu çözmek için JSON yapınızı gerçekten iyileştirmelisiniz:

$scope.testData = [
   {name:"CData", order: 1},
   {name:"BData", order: 2},
   {name:"AData", order: 3},
]

O zaman yapabilirsin

<li ng-repeat="test in testData | orderBy:order">...</li>

Bence sorun, (anahtar, değer) değişkenlerinin orderBy filtresinde mevcut olmaması ve yine de anahtarlarınızda veri depolamamanız gerektiğidir.


2
bunu Firebase'e söyle;)
MFB

bildiğim kadarıyla verileri firebase'de oluşturuyorsunuz
Joshua Wooward

Firebase'de bir dizi depolarsanız, dizi için anahtar olarak bir UID kullanır. Veri yapısı üzerinde kontrolün olmadığı birçok durum vardır, bu nedenle öneriniz biraz kapsamlı olabilir.
MFB

bir dizi neyi depolamak? Veri yapısı her zaman kontrol edilebilir. Ayrıca OP, Firebase hakkında hiçbir şeyden bahsetmez.
Joshua Wooward

2

İşte yaptığım şey ve işe yarıyor.
Az önce telli bir nesne kullandım.

$scope.thread = [ 
  {
    mostRecent:{text:'hello world',timeStamp:12345678 } 
    allMessages:[]
  }
  {MoreThreads...}
  {etc....}
]

<div ng-repeat="message in thread | orderBy : '-mostRecent.timeStamp'" >

metne göre sıralamak isteseydim yapardım

orderBy : 'mostRecent.text'

2

Sonraki sözdizimini destekleyebilecek yükseltilmiş filtre sürümümü ekleyeceğim:

ng-repeat="(id, item) in $ctrl.modelData | orderObjectBy:'itemProperty.someOrder':'asc'

app.filter('orderObjectBy', function(){

         function byString(o, s) {
            s = s.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
            s = s.replace(/^\./, '');           // strip a leading dot
            var a = s.split('.');
            for (var i = 0, n = a.length; i < n; ++i) {
                var k = a[i];
                if (k in o) {
                    o = o[k];
                } else {
                    return;
                }
            }
            return o;
        }

        return function(input, attribute, direction) {
            if (!angular.isObject(input)) return input;

            var array = [];
            for(var objectKey in input) {
                if (input.hasOwnProperty(objectKey)) {
                    array.push(input[objectKey]);
                }
            }

            array.sort(function(a, b){
                a = parseInt(byString(a, attribute));
                b = parseInt(byString(b, attribute));
                return direction == 'asc' ? a - b : b - a;
            });
            return array;
        }
    })

İçinde Armin ve bu iplik onların cevaplar Jason ve Alnitak sayesinde bu konuya .


1

Armin'in cevabı + nesne türleri ve açısal olmayan anahtarlar için katı bir kontrol $resolve

app.filter('orderObjectBy', function(){
 return function(input, attribute) {
    if (!angular.isObject(input)) return input;

    var array = [];
    for(var objectKey in input) {
      if (typeof(input[objectKey])  === "object" && objectKey.charAt(0) !== "$")
        array.push(input[objectKey]);
    }

    array.sort(function(a, b){
        a = parseInt(a[attribute]);
        b = parseInt(b[attribute]);
        return a - b;
    });

    return array;
 }
})

1

Aşağıdakiler, nesnelerin anahtarla VEYA bir nesne içindeki bir anahtarla sıralanmasına izin verir .

Şablonda aşağıdaki gibi bir şey yapabilirsiniz:

    <li ng-repeat="(k,i) in objectList | orderObjectsBy: 'someKey'">

Ya da:

    <li ng-repeat="(k,i) in objectList | orderObjectsBy: 'someObj.someKey'">

Filtre:

app.filter('orderObjectsBy', function(){
 return function(input, attribute) {
    if (!angular.isObject(input)) return input;

    // Filter out angular objects.
    var array = [];
    for(var objectKey in input) {
      if (typeof(input[objectKey])  === "object" && objectKey.charAt(0) !== "$")
        array.push(input[objectKey]);
    }

    var attributeChain = attribute.split(".");

    array.sort(function(a, b){

      for (var i=0; i < attributeChain.length; i++) {
        a = (typeof(a) === "object") && a.hasOwnProperty( attributeChain[i]) ? a[attributeChain[i]] : 0;
        b = (typeof(b) === "object") && b.hasOwnProperty( attributeChain[i]) ? b[attributeChain[i]] : 0;
      }

      return parseInt(a) - parseInt(b);
    });

    return array;
 }
})

objectList'teki (k, i) anahtarlarının 0'lara ve 1'lere dönüştürülmesi normal mi?
Ken Vernaillen
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.