Fungsi pengurutan kustom dalam ng-repeat


113

Saya memiliki satu set ubin yang menampilkan angka tertentu tergantung pada opsi mana yang dipilih oleh pengguna. Sekarang saya ingin menerapkan pengurutan berdasarkan nomor apa pun yang ditampilkan.

Kode di bawah ini menunjukkan bagaimana saya menerapkannya (dengan mendapatkan / menetapkan nilai dalam cakupan kartu induk). Sekarang, karena fungsi orderBy mengambil string, saya mencoba menetapkan variabel dalam cakupan kartu yang disebut curOptionValue dan mengurutkan berdasarkan itu, tetapi tampaknya tidak berhasil.

Jadi pertanyaannya menjadi, bagaimana cara membuat fungsi sortir kustom?

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

dan pengontrol:

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

Jawaban:


192

Sebenarnya orderByfilter dapat mengambil parameter tidak hanya sebagai string tetapi juga fungsi. Dari orderBydokumentasi: https://docs.angularjs.org/api/ng/filter/orderBy ):

Fungsi: Fungsi getter. Hasil dari fungsi ini akan diurutkan menggunakan operator <, =,>.

Jadi, Anda bisa menulis fungsi Anda sendiri. Misalnya, jika Anda ingin membandingkan kartu berdasarkan jumlah opt1 dan opt2 (saya mengarangnya, intinya adalah Anda dapat memiliki fungsi arbitrer), Anda akan menulis di pengontrol:

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

dan kemudian, di template Anda:

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

Inilah jsFiddle yang berfungsi

Hal lain yang perlu diperhatikan adalah itu orderByhanya salah satu contoh filter AngularJS jadi jika Anda memerlukan perilaku pengurutan yang sangat spesifik, Anda dapat menulis filter Anda sendiri (walaupun orderByseharusnya cukup untuk sebagian besar kasus penggunaan).


Itu bagus, tapi mungkinkah membuat filter untuk itu juga?
hugo der hungrige

Ya, ini masih berfungsi. Ini adalah versi yang diperbarui
jahller

Mengapa tidak ada deskripsi tentang beberapa parameter di dokumen ?? BTW: Terima kasih, berhasil. :)
mayankcpdixit

Tahukah Anda bagaimana saya dapat menangani beberapa kriteria dengan pendekatan ini? Bagaimana cara mengembalikan beberapa nilai dari myValueFunction?
akcasoy

26

Solusi yang diterima hanya berfungsi pada array, tetapi tidak pada objek atau array asosiatif. Sayangnya, karena Angular bergantung pada implementasi JavaScript dari enumerasi array, urutan properti objek tidak dapat dikontrol secara konsisten. Beberapa browser mungkin melakukan iterasi melalui properti objek secara leksikografis, tetapi ini tidak dapat dijamin.

misalnya Diberikan tugas berikut:

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

dan perintahnya <ul ng-repeat="(key, card) in cards | orderBy:myValueFunction">, ng-repeat dapat mengulang "card1" sebelum "card2", apa pun urutannya.

Untuk mengatasinya, kita bisa membuat filter kustom untuk mengonversi objek menjadi array, lalu menerapkan fungsi sortir kustom sebelum mengembalikan koleksi.

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

Kita tidak dapat mengulang pasangan (key, value) bersama dengan filter kustom (karena kunci untuk array adalah indeks numerik), jadi template harus diperbarui untuk mereferensikan nama kunci yang dimasukkan.

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

Berikut ini biola yang berfungsi menggunakan filter khusus pada array asosiatif: http://jsfiddle.net/av1mLpqx/1/

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


1
Aku tahu seharusnya aku tidak melakukannya, tetapi aku hanya harus - Terima kasih.
Elia Weiss

7

Tautan berikut menjelaskan filter di Angular dengan sangat baik. Ini menunjukkan bagaimana mungkin untuk mendefinisikan logika sortir kustom dalam ng-repeat. http://toddmotto.com/everything-about-custom-filters-in-angular-js

Untuk mengurutkan objek dengan properti, ini adalah kode yang saya gunakan: (Perhatikan bahwa pengurutan ini adalah metode pengurutan JavaScript standar dan tidak khusus untuk sudut) Nama Kolom adalah nama properti tempat pengurutan akan dilakukan.

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

0

Untuk memasukkan arah bersama dengan fungsi orderBy:

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

dimana

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

emmmmm, hanya lewat pikiran saya mengamati bahwa Anda menulis myOrderbyFunction()sebagai gantinya Anda harus menulis myOrderbyFunctiontanpa (), itu akan dipanggil untuk setiap dua pasang elemen agar Anda memberikan penyortiran kustom.
Victor
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.