Angularjs siparişten sonra yanlış $ endeksi


92

Angular.js'de yeniyim ve dizimi sıralarken ve bu sıralanmış veriler üzerinde çalışırken bazı sorunlar yaşıyorum.

Öğeler içeren bir listem var ve şimdiye kadar çalışan "Store.storeName" e göre sıralamak istiyorum. Ancak verileri sıraladıktan sonra silme işlevim artık çalışmıyor. Sanırım bunun nedeni sıralamanın ardından $ endeksinin yanlış olması ve dolayısıyla yanlış verilerin silinmesi.

Bunu nasıl çözebilirim? Görünümde değil kapsamdaki verileri mi sipariş ediyorsunuz? Bu nasıl yapılır?

İşte bazı ilgili kodlar:

Görünümde:

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

Denetleyicimde, belirli verileri silmesi gereken bu silme işlevine sahibim:

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

Bu, Görünümde sipariş vermeden önce iyi çalışıyor. Önemli bir şey eksikse, lütfen şimdi izin verin.

Teşekkürler!

Yanıtlar:


140

Bunun yerine veya $index- fark ettiğiniz gibi - sıralı / filtrelenmiş bir dizideki dizine işaret edecek, öğenin kendisini removeItemişlevinize aktarabilirsiniz :

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

ve aşağıdaki gibi bir dizinin yöntemini removeItemkullanarak bir dizin bulmak için işlevi değiştirin indexOf:

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

1
@ pkozlowski.opensource Sen bir dahisin! Bir öğeyi indekslemeden geçebilirsiniz .. Vay canına !! Teşekkürler dostum.
good_evening

Array indexOf, Internet Explorer 8 ve önceki sürümlerde kullanılamaz.
Peter Hedberg

4
Soru başlığı, orderBy'den sonra yanlış bir $ endeksi soruyor, bu yanıt bu yanıtı ele almıyor. Doğru $ endeks değerine ihtiyaç duyduğunuz durumlar vardır (bir listede vardiya seçimi gibi). OrderBy filtresi uygulandıktan sonra doğru $ endeksi değerini nasıl elde ederiz?
ClearCloud8

ayrıca şablondaki sıralı listeden yeni bir dizi de oluşturabilirsiniz: "sıralı_aray = (dizi | filtre: filtre | orderBy: order_by)"
Porlune

Düzgün! Sağ ol, kanka.
CENT1PEDE

23

Açısal öğrenmeye başladım ve benzer sorunlarla karşılaştım ve @ pkozlowski-opensource'un cevabından yola çıkarak, bunu sadece şöyle bir şeyle çözdüm:

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

1
Bu, özel filtre vb. Oluşturmaktansa en iyisi ve çok basit. +1
Rafique Mohammed

1
bu nasıl doğru cevap değil? Bu benim sorunumu çözdü
Cyrus Zei

19

Aynı sorunu yaşadım ve bu konudaki diğer cevaplar durumuma uygun değil.

Sorunumu özel filtre ile çözdüm:

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

bu şekilde kullanılabilir:

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

ve sonra HTML'de item.indexyerine kullanabilirsiniz $index.

Bu yöntem, nesnelerin koleksiyonları için uygundur.

Lütfen, bu özel filtrenin uygulanan tüm filtreler (orderBy vb.) Listesinde ilk olması gerektiğini indexve koleksiyonun her bir nesnesine ek özelliği (ad özelleştirilebilir) ekleyeceğini dikkate alın.


Diğer cevapların sizin durumunuza neden uygun olmadığını biraz açıklar mısınız?
pkozlowski.opensource

1
@ pkozlowski.opensource Bu çok daha temiz. Ayrıca hangi olayların eklenebileceğine ve indexOf'daki öğelerin karmaşıklığına bağlı olarak çok daha verimli. Ayrıca $scope.items.splice($scope.items.indexOf(item),1);yinelenen öğeler için beklendiği gibi çalışmaz.
martin

1
@martin performansla ilgili iddialarınızı gerçek rakamlarla yedeklemelisiniz. Bir filtrenin her $ sindirim döngüsünde çalıştırılma gibi büyük bir dezavantajı vardır, bu yüzden performansa yardımcı olduğunu düşünmüyorum ...
pkozlowski.opensource

@ pkozlowski.opensource Bu doğru ve her $ sindirim döngüsü için iki kez çalışıyor. Önemli olan "hangi olayların eklenebileceğine bağlı olarak", hız üzerinde hiçbir kontrolünüz olmadığında performans önemlidir, örneğin, kısılmamış kaydırma olayı - aşırı durum biliyorum.
martin

@mile İyi kopyalarım var ve aradığım şey buydu, Angular'ın $ değişkeninde orijinal dizini takip etmemesi biraz üzücü. denedim (key, item) in itemsve çalışmıyor. (anahtar orijinalde tutulmaz)
Rouche

4

Bunu dene:

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

}

Blogumdaki bu girişte ayrıntılı açıklamalar bulabilirsiniz .


2

Birinin kullanması $indexgerektiğinde, sıralanmış / filtrelenmiş diziye bir ad verebilirsiniz:

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

Cevabımı burada görün .


Ayrıntılardan yoksunsa bu cevabın iyi olduğunu düşünüyorum. Sanırım hmk'nin anlamı, filtrelenmiş liste bir kez bir kenara bırakıldıktan sonra, indeksin istenen girişi almak için ona karşı (yani "sıralanmışItems [$ indeks]") kullanılabileceğidir.
Jeremythuff

1

Bir yorum bırakacaktım ama "itibarım" yok.

mil çözümü tam da ihtiyacım olan şeydi. Pkozlowski.opensource'un sorusunu yanıtlamak için: iç içe geçmiş ngRepeate- postalarınız , dinamik bir listeniz (ör. Kaldırmaya izin verdiğiniz yer ) veya her ikisine sahip olduğunuzda (bu benim durumum), $indexarka uç için yanlış dizin olacağı için kullanmak işe yaramıyor verileri sıraladıktan ve ngInitönbelleğe almak için kullandıktan sonra , liste değiştiğinde yeniden değerlendirilmediğinden değer çalışmaz.

Mile çözümünün, ekli dizin özelliği adının bir parametre iletilerek özelleştirilmesine izin verdiğini unutmayın. <tr ng-repeat="item in items | index:'originalPosition' | orderBy:'Store.storeName'">

Tweaked versiyonum:

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