Angularjs salah $ index setelah orderBy

92

Saya baru mengenal Angular.js dan memiliki beberapa masalah dalam menyortir array saya dan mengerjakan data yang diurutkan.

Saya memiliki daftar dengan item dan ingin mengurutkannya berdasarkan "Store.storeName", yang berfungsi sejauh ini. Tetapi setelah menyortir data, fungsi hapus saya tidak berfungsi lagi. Saya pikir itu karena $ index salah setelah penyortiran, sehingga data yang salah dihapus.

Bagaimana saya bisa mengatasinya? Mengurutkan data dalam lingkup dan bukan dalam tampilan? Bagaimana cara melakukannya?

Berikut beberapa kode yang relevan:

Dalam Tampilan:

<tr ng-repeat="item in items | orderBy:'Store.storeName'">
                <td><input class="toggle" type="checkbox" ng-model="item.Completed"></td>
                <td>{{item.Name}}</td>
                <td>{{item.Quantity}} Stk.</td>
                <td>{{item.Price || 0 | number:2}} €</td>                
                <td>{{item.Quantity*item.Price|| 0 | number:2}} €</td>
                <td>{{item.Store.storeName}}</td> 
                <td><a><img src="img/delete.png" ng-click="removeItem($index)">{{$index}}</a></td>
            </tr>

Dan di pengontrol saya, saya memiliki fungsi hapus ini, yang seharusnya menghapus data tertentu:

$scope.removeItem = function(index){
        $scope.items.splice(index,1);
    }

Ini bekerja dengan baik sebelum memesan di Tampilan. Jika ada sesuatu yang penting hilang, tolong beri tahu saya sekarang.

Terima kasih!

FuzzBuzz
sumber

Jawaban:

140

Alih-alih atau menyampaikan $index- yang - seperti yang Anda perhatikan - akan mengarah ke indeks dalam larik yang diurutkan / difilter, Anda dapat meneruskan item itu sendiri ke removeItemfungsi Anda :

<a><img src="img/delete.png" ng-click="removeItem(item)">{{$index}}</a>

dan modifikasi removeItemfungsi untuk menemukan indeks menggunakan indexOfmetode array sebagai berikut:

$scope.removeItem = function(item){
   $scope.items.splice($scope.items.indexOf(item),1);
}
pkozlowski.opensource
sumber
1
@ pkozlowski.opensource Anda seorang jenius! Anda dapat mengirimkan item, bukan indeks .. Wow !! Terima kasih sobat.
good_evening
Array indexOf tidak tersedia di Internet Explorer 8 dan yang lebih rendah.
Peter Hedberg
4
Judul pertanyaan menanyakan tentang kesalahan $ index setelah orderBy, yang tidak ditangani oleh jawaban ini. Ada kasus di mana Anda memerlukan nilai $ indeks yang benar (seperti shift pilih pada daftar). Bagaimana kita mendapatkan nilai $ indeks yang benar setelah filter orderBy diterapkan?
ClearCloud8
Anda juga dapat membuat array baru dari daftar terurut dalam template dengan melakukan sesuatu seperti ini: "ele in order_array = (array | filter: filter | orderBy: order_by)"
Porlune
Rapi! Makasih bro.
CENT1PEDE
23

Saya mulai belajar sudut dan menghadapi masalah serupa, dan berdasarkan jawaban dari @ pkozlowski-opensource, saya menyelesaikannya hanya dengan sesuatu seperti

<a>
  <img src="img/delete.png" ng-click="removeItem(items.indexOf(item))">
  {{items.indexOf(item)}}
</a> 
ad_nm
sumber
1
Ini yang terbaik dan sangat sederhana daripada membuat filter ubahsuaian, dll. +1
Rafique Mohammed
1
bagaimana ini bukan jawaban yang benar? Ini memecahkan masalah saya
Cyrus Zei
19

Saya memiliki masalah yang sama dan jawaban lain dalam topik ini tidak sesuai dengan situasi saya.

Saya telah menyelesaikan masalah saya dengan filter khusus:

angular.module('utils', []).filter('index', function () {
    return function (array, index) {
        if (!index)
            index = 'index';
        for (var i = 0; i < array.length; ++i) {
            array[i][index] = i;
        }
        return array;
    };
});

yang dapat digunakan dengan cara ini:

<tr ng-repeat="item in items | index | orderBy:'Store.storeName'">

dan kemudian dalam HTML Anda dapat menggunakan item.indexbukan $index.

Metode ini cocok untuk koleksi objek.

Harap perhatikan bahwa filter ubahsuaian ini harus menjadi yang pertama dalam daftar semua filter yang diterapkan (orderBy, dll.) Dan ini akan menambahkan properti tambahan index(namanya dapat disesuaikan) ke dalam setiap objek koleksi.

mil
sumber
Bisakah Anda menjelaskan mengapa jawaban lain tidak sesuai dengan situasi Anda?
pkozlowski.opensource
1
@ pkozlowski.opensource Ini jauh lebih bersih. Juga tergantung pada peristiwa apa yang bisa dilampirkan, dan kompleksitas item di indexOf jauh lebih efisien. Juga $scope.items.splice($scope.items.indexOf(item),1);tidak akan berfungsi seperti yang diharapkan untuk item duplikat.
martin
1
@martin Anda harus mendukung klaim Anda mengenai kinerja dengan bilangan real. Filter memiliki kerugian besar karena dieksekusi pada setiap siklus $ digest jadi saya rasa itu tidak membantu kinerja ...
pkozlowski.opensource
@ pkozlowski.opensource Itu benar, dan ini berjalan dua kali untuk setiap siklus $ digest. Hal yang penting adalah "tergantung pada peristiwa apa yang dapat dilampirkan", kinerja penting ketika Anda tidak memiliki kendali atas laju, misalnya, peristiwa gulir yang tidak dibatasi - kasus ekstrem yang saya tahu.
martin
@mile Yah saya punya duplikat dan inilah yang saya cari, hanya sedikit sedih Angular tidak melacak atau indeks asli dalam variabel $. saya mencoba (key, item) in itemsdan tidak berhasil. (kunci tidak disimpan ke aslinya)
Rouche
4

Coba ini:

$scope.remove = function(subtask) {

    var idx = $scope.subtasks.indexOf(subtask),
        st = $scope.currentTask.subtasks[idx];

    // remove from DB
    SubTask.remove({'subtaskId': subtask.id});

    // remove from local array
    $scope.subtasks.splice(idx,1);

}

Anda dapat menemukan penjelasan panjang lebar di entri ini di blog saya.

Dmitry Dushkin
sumber
2

Jika seseorang perlu menggunakan $index, Anda dapat memberi nama pada array yang diurutkan / difilter:

<tr ng-repeat="item in sortedItems = (items | orderBy:'Store.storeName') track by $index">

Lihat jawaban saya di sini .

hmk
sumber
Saya pikir jawaban ini baik-baik saja, jika kurang detail. Saya pikir apa yang dimaksud dengan hmk adalah bahwa setelah daftar yang difilter telah disisihkan, seperti di atas, indeks dapat digunakan untuk melawannya (yaitu "sortItems [$ index]") untuk mengambil entri yang diinginkan.
Jeremythuff
1

Saya akan meninggalkan komentar, tetapi saya tidak memiliki "reputasi".

solusi mil adalah apa yang saya butuhkan juga. Untuk menjawab pertanyaan pkozlowski.opensource: ketika Anda memiliki ngRepeats bersarang , daftar dinamis (misalnya di mana Anda mengizinkan penghapusan), atau keduanya (yang merupakan kasus saya), menggunakan $indextidak berfungsi karena akan menjadi indeks yang salah untuk back-end data setelah pengurutan dan penggunaan ngInituntuk menyimpan ke cache, nilai juga tidak berfungsi karena tidak dievaluasi ulang saat daftar berubah.

Perhatikan bahwa solusi mile memungkinkan nama properti indeks yang dilampirkan dikustomisasi dengan meneruskan parameter <tr ng-repeat="item in items | index:'originalPosition' | orderBy:'Store.storeName'">

Versi tweak saya:

.filter( 'repeatIndex', function repeatIndex()
{
// This filter must be called AFTER 'filter'ing 
//  and BEFORE 'orderBy' to be useful.
    return( function( array, index_name )
    {
        index_name = index_name || 'index';
        array.forEach( function( each, i )
        {each[ index_name ] = i;});
        return( array );
    });
})
MarkMYoung
sumber