Ng tekrarında özel sıralama işlevi


113

Kullanıcı tarafından hangi seçeneğin seçildiğine bağlı olarak belirli bir sayı gösteren bir dizi döşemem var. Şimdi, gösterilen sayıya göre bir sıralama uygulamak istiyorum.

Aşağıdaki kod, onu nasıl uyguladığımı gösterir (ana kartlar kapsamında bir değer alarak / ayarlayarak). Şimdi, orderBy işlevi bir dizge aldığından, kart kapsamında curOptionValue adlı bir değişken ayarlamaya ve buna göre sıralamayı denedim, ancak işe yaramıyor.

Öyleyse soru, özel bir sıralama işlevi nasıl oluşturabilirim?

<div ng-controller="aggViewport" >
<div class="btn-group" >
    <button ng-click="setOption(opt.name)" ng-repeat="opt in optList" class="btn active">{{opt.name}}</button>
</div>
<div id="container" iso-grid width="500px" height="500px">
    <div ng-repeat="card in cards" class="item {{card.class}}" ng-controller="aggCardController">
        <table width="100%">
            <tr>
                <td align="center">
                    <h4>{{card.name}}</h4>
                </td>
            </tr>
            <tr>
                <td align="center"><h2>{{getOption()}}</h2></td>
            </tr>
        </table>        
    </div>
</div>

ve denetleyici:

module.controller('aggViewport',['$scope','$location',function($scope,$location) {
    $scope.cards = [
        {name: card1, values: {opt1: 9, opt2: 10}},
        {name: card1, values: {opt1: 9, opt2: 10}}
    ];

    $scope.option = "opt1";

    $scope.setOption = function(val){
        $scope.option = val;
    }

}]);

module.controller('aggCardController',['$scope',function($scope){
    $scope.getOption = function(){
        return $scope.card.values[$scope.option];
    }
}]);

Yanıtlar:


192

Aslında orderByfiltre, parametre olarak yalnızca bir dizgeyi değil, aynı zamanda bir işlevi de alabilir. Gönderen orderBy: belgelerine https://docs.angularjs.org/api/ng/filter/orderBy ):

işlevi: Alıcı işlevi. Bu işlevin sonucu <, =,> operatörü kullanılarak sıralanacaktır.

Böylece kendi fonksiyonunuzu yazabilirsiniz. Örneğin, kartları bir opt1 ve opt2 toplamına göre karşılaştırmak isterseniz (bunu ben uyduruyorum, önemli olan, herhangi bir isteğe bağlı işleve sahip olabileceğinizdir) denetleyicinize yazarsınız:

$scope.myValueFunction = function(card) {
   return card.values.opt1 + card.values.opt2;
};

ve sonra şablonunuzda:

ng-repeat="card in cards | orderBy:myValueFunction"

İşte çalışan jsFiddle

Dikkate değer diğer bir şey de orderBy, AngularJS filtrelerinin yalnızca bir örneğidir, bu nedenle çok özel bir sıralama davranışına ihtiyacınız varsa, kendi filtrenizi yazabilirsiniz (ancak orderByçoğu kullanım durumu için yeterli olmalıdır).


Bu güzel, ama bunun için de bir filtre oluşturmak mümkün mü?
hugo der hungrige

Evet, hala çalışıyor. İşte güncellenmiş bir sürüm
jahller

Dokümanlarda birden çok parametre hakkında neden açıklama yok? BTW: Teşekkürler, işe yarıyor. :)
mayankcpdixit

Bu yaklaşımla birden çok kriteri nasıl ele alabileceğimi biliyor musunuz? MyValueFunction'dan birden çok değeri nasıl döndürebilirim?
akcasoy

26

Kabul edilen çözüm yalnızca diziler üzerinde çalışır, nesneler veya ilişkilendirilebilir diziler üzerinde çalışmaz. Ne yazık ki Angular, dizi numaralandırmasının JavaScript uygulamasına bağlı olduğundan, nesne özelliklerinin sırası tutarlı bir şekilde kontrol edilemez. Bazı tarayıcılar, nesne özelliklerini sözlükbilimsel olarak yineleyebilir, ancak bu garanti edilemez.

Örneğin, aşağıdaki atama verildiğinde:

$scope.cards = {
  "card2": {
    values: {
      opt1: 9,
      opt2: 12
    }
  },
  "card1": {
    values: {
      opt1: 9,
      opt2: 11
    }
  }
};

ve <ul ng-repeat="(key, card) in cards | orderBy:myValueFunction">ng-tekrar yönergesi , sıralama düzenine bakılmaksızın, "kart2" den önce "kart1" üzerinde yinelenebilir.

Bunu geçici olarak çözmek için, nesneyi bir diziye dönüştürmek için özel bir filtre oluşturabilir ve ardından koleksiyonu döndürmeden önce özel bir sıralama işlevi uygulayabiliriz.

myApp.filter('orderByValue', function () {
  // custom value function for sorting
  function myValueFunction(card) {
    return card.values.opt1 + card.values.opt2;
  }

  return function (obj) {
    var array = [];
    Object.keys(obj).forEach(function (key) {
      // inject key into each object so we can refer to it from the template
      obj[key].name = key;
      array.push(obj[key]);
    });
    // apply a custom sorting function
    array.sort(function (a, b) {
      return myValueFunction(b) - myValueFunction(a);
    });
    return array;
  };
});

Özel filtrelerle birlikte (anahtar, değer) çiftlerini yineleyemeyiz (diziler için anahtarlar sayısal dizinler olduğundan), bu nedenle şablon, enjekte edilen anahtar adlarına başvuracak şekilde güncellenmelidir.

<ul ng-repeat="card in cards | orderByValue">
    <li>{{card.name}} {{value(card)}}</li>
</ul>

İlişkili bir dizide özel bir filtre kullanan çalışan bir keman: http://jsfiddle.net/av1mLpqx/1/

Referans: https://github.com/angular/angular.js/issues/1286#issuecomment-22193332


1
Yapmamam gerektiğini biliyorum ama sadece yapmalıyım - Teşekkürler.
Elia Weiss

7

Aşağıdaki bağlantı, Angular'daki filtreleri son derece iyi açıklamaktadır. Bir ng-tekrarında özel sıralama mantığını tanımlamanın nasıl mümkün olduğunu gösterir. http://toddmotto.com/everything-about-custom-filters-in-angular-js

Nesneyi özelliklerle sıralamak için kullandığım kod budur: (Bu sıralamanın standart JavaScript sıralama yöntemi olduğunu ve açılıya özgü olmadığını unutmayın) Sütun Adı, üzerinde sıralamanın gerçekleştirileceği özelliğin adıdır.

self.myArray.sort(function(itemA, itemB) {
    if (self.sortOrder === "ASC") {
        return itemA[columnName] > itemB[columnName];
    } else {
        return itemA[columnName] < itemB[columnName];
    }
});

0

Yönü orderBy işleviyle birlikte eklemek için:

ng-repeat="card in cards | orderBy:myOrderbyFunction():defaultSortDirection"

nerede

defaultSortDirection = 0; // 0 = Ascending, 1 = Descending

emmmmm, sadece geçen i yazdığın gözlemlemek düşünce myOrderbyFunction()yerine yazacak myOrderbyFunctionolmadan ()bunu sıralama özel sağlamak amacıyla elemanların her iki çifti için çağrılan.
Victor
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.