AngularJS - ngRepeat filtreli sonuç referansı nasıl alınır


129

Şu şekilde filtreli bir ng-tekrar yönergesi kullanıyorum:

ng-repeat="item in items | orderBy:'order_prop' | filter:query | limitTo:4"

ve işlenmiş sonuçları iyi görebiliyorum; şimdi denetleyicimde bu sonuç üzerinde biraz mantık çalıştırmak istiyorum. Soru, sonuç öğelerinin referansını nasıl alabilirim?

Güncelleme:


Sadece açıklığa kavuşturmak için: Bir otomatik tamamlama oluşturmaya çalışıyorum, şu girdiye sahibim:

<input id="queryInput" ng-model="query" type="text" size="30" placeholder="Enter query">

ve ardından filtrelenen sonuçlar:

<ul>
   <li  ng-repeat="item in items | orderBy:'order_prop' | filter:query | limitTo:4">{{item.name}}</li>
</ul>

şimdi sonuçta gezinmek ve öğelerden birini seçmek istiyorum.

Yanıtlar:


271

GÜNCELLEME : İşte daha önce olduğundan daha kolay bir yol.

 <input ng-model="query">
 <div ng-repeat="item in (filteredItems = (items | orderBy:'order_prop' | filter:query | limitTo:4))">
   {{item}}
 </div>

O zaman $scope.filteredItemserişilebilir.


Cevabınız için teşekkürler, lütfen güncellememe bakın. Bunu nasıl uygularsınız, tüm öğeler listesini init'te aldığımı unutmayın
Shlomi Schwartz

süper havalı, bunun için teşekkürler. Keşke
NG'nin

3
Bu yaklaşımla ilgili sorun, atanmış mülkü izlerseniz, sonunda $ özet (yineleme başına bir) spam göndermenizdir ... Belki bundan kaçınmanın bir yolu vardır?
Juho Vepsäläinen

1
Arama nesnesini ve console.log'u izlersem filteredItems, verileri her zaman bir filtre sonra alırım. Bu, yeni değiştirilen filtrenin değil, önceki değişikliğin sonucudur. Herhangi bir fikir?
ProblemsOfSumit

4
Biri bana açıklayabilir mi, bu neden işe yarıyor? $ Kapsamındaki bir değişkenin yineleme kapsamında erişilebilir olduğunu anlayabiliyorum (kapsam devralma), ancak tam tersi? Nasıl? Bazı belgeler takdir edilmektedir. Teşekkürler
dalvarezmartinez1

30

İşte Andy Joslin'in çözümünün filtre versiyonu.

Güncelleme: BREAKING CHANGE. 1.3.0-beta.19 sürümünden itibaren ( bu kaydetme ) filtrelerinin bir içeriği yoktur ve thisgenel kapsama bağlı olacaktır. Bağlamı bağımsız değişken olarak iletebilir veya ngRepeat , 1.3.0-beta.17 + ' daki yeni takma ad sözdizimini kullanabilirsiniz .

// pre 1.3.0-beta.19
yourModule.filter("as", function($parse) {
  return function(value, path) {
    return $parse(path).assign(this, value);
  };
});

// 1.3.0-beta.19+
yourModule.filter("as", function($parse) {
  return function(value, context, path) {
    return $parse(path).assign(context, value);
  };
});

Sonra senin görüşünde

<!-- pre 1.3.0-beta.19 -->
<input ng-model="query">
<div ng-repeat="item in items | orderBy:'order_prop' | filter:query | limitTo:4 | as:'filteredItems'">
 {{item}}
</div>

<!-- 1.3.0-beta.19+ -->
<input ng-model="query">
<div ng-repeat="item in items | orderBy:'order_prop' | filter:query | limitTo:4 | as:this:'filteredItems'">
 {{item}}
</div>

<!-- 1.3.0-beta.17+ ngRepeat aliasing -->
<input ng-model="query">
<div ng-repeat="item in items | orderBy:'order_prop' | filter:query | limitTo:4 as filteredItems">
 {{item}}
</div>

Bu size erişim sağlar $scope.filteredItems.


Teşekkürler! Filtre kodunun nasıl çalıştığını açıklayabilir misiniz? $ Parse konusuna aşina değilim ve açısal dokümanlar, filtrenizin tam olarak nasıl çalıştığını çözmeme yardımcı olmadı.
Magne

2
@Magne Sorun değil! Size biraz acı ve acı çekmeyeceği için lütfen güncellemeye göz atın. Sorunuzu cevaplamak için Kısacası, $parseaçısal en olduğunu ifade derleyici .. Örneğin, belirli bir için bahsedilen yolun bir değer dizesi 'some.object.property' almak ve ya setine olanak tanıyan bir işlev döndürecek veya alırsınız bağlamı. Özellikle burada $ kapsamında filtre sonuçlarını ayarlamak için kullanıyorum. Umarım bu soru sorunuzu yanıtlamıştır.
kevinjamesus86

23

Bunun gibi bir şey deneyin, ng-tekrarı ile ilgili sorun, erişemediğiniz için çocuk kapsamı yaratmasıdır.

filteritems

denetleyiciden

<li ng-repeat="doc in $parent.filteritems = (docs | filter:searchitems)" ></li>

16

Güncelleme:

1.3.0'dan sonra bile. Eğer onu denetleyicinin veya üst öğenin kapsamına koymak istiyorsanız, bunu sözdizimi olarak yapamazsınız . Örneğin, aşağıdaki koda sahipsem:

<div>{{labelResults}}</div>
<li ng-repeat="label in (labels | filter:query | as labelResults)">
</div>

Yukarıdaki olacak değil iş. Etrafından dolaşmanın yolu $ parent'i şu şekilde kullanmaktır:

<li ng-repeat="label in ($parent.labelResults = (labels | filter:query))">

Bunu filtrelemek için bir limitiniz varsa not etmek iyidir. $ Parent.labelResults
Zack

I Eğer console.log labelResultsHep sonradan veri bir filtre olsun. Bu, yeni değiştirilen filtrenin değil, önceki değişikliğin sonucudur. Bu sorunu yaşamadın mı?
Anna

10

Andy'nin çözümünün biraz daha iyi bir versiyonunu buldum. Kendi çözümünde ng-tekrar, ödevi içeren ifadeye bir saat yerleştirir. Her özet döngüsü bu ifadeyi değerlendirecek ve sonucu kapsam değişkenine atayacaktır.

Bu çözümle ilgili sorun, alt kapsamda iseniz atama sorunlarıyla karşılaşabilmenizdir. Bu, ng modelinde bir noktaya sahip olmanızın aynı nedenidir .

Bu çözümle ilgili hoşlanmadığım bir diğer şey, filtrelenmiş dizinin tanımını görünüm işaretlemesinde bir yere gömmesidir. Görüşünüzde veya kontrol cihazınızda birden fazla yerde kullanılırsa kafa karıştırıcı olabilir.

Daha basit bir çözüm, denetleyicinize atamayı yapan bir işlevin üzerine bir saat yerleştirmektir:

$scope.$watch(function () {
    $scope.filteredItems = $scope.$eval("items | orderBy:'order_prop' | filter:query | limitTo:4");
});

Bu işlev her bir sindirim döngüsü sırasında değerlendirilecektir, bu nedenle performans Andy'nin çözümüyle karşılaştırılabilir olmalıdır. Ayrıca, fonksiyona istediğiniz sayıda atama ekleyerek bunların tümünü görünümde dağınık halde tutmak yerine tek bir yerde tutabilirsiniz.

Görünümde, filtrelenmiş listeyi doğrudan kullanırsınız:

<ul>
    <li  ng-repeat="item in filteredItems">{{item.name}}</li>
</ul>

İşte bunun daha karmaşık bir senaryoda gösterildiği bir keman.


Süper temiz ve yapıyı kirletmez, güzel!
kuzyn

bu çözüm benim için mükemmel .. tekrarlamak yerine iyonik koleksiyon tekrarını kullanıyordum ... bu yüzden kabul edilen cevap benim için işe yaramadı
Lakshay

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.