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

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

pkozlowski.opensource
sumber
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

David
sumber
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];
    }
});
Jonathan Cardoz
sumber
0

Untuk memasukkan arah bersama dengan fungsi orderBy:

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

dimana

defaultSortDirection = 0; // 0 = Ascending, 1 = Descending
Ben
sumber
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