AngularJS - cara mendapatkan referensi hasil yang disaring ngRepeat

129

Saya menggunakan arahan ng-repeat dengan filter seperti ini:

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

dan saya bisa melihat hasil yang diberikan baik-baik saja; sekarang saya ingin menjalankan beberapa logika pada hasil itu di controller saya. Pertanyaannya adalah bagaimana saya bisa mengambil referensi item hasil?

Memperbarui:


Hanya untuk mengklarifikasi: Saya mencoba membuat pelengkapan otomatis, saya mendapat masukan ini:

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

dan kemudian hasil yang disaring:

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

sekarang saya ingin menavigasi hasilnya dan memilih salah satu item.

Shlomi Schwartz
sumber

Jawaban:

270

UPDATE : Ini cara yang lebih mudah daripada apa yang ada sebelumnya.

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

Kemudian $scope.filteredItemsdapat diakses.

Andrew Joslin
sumber
Terima kasih atas jawabannya, silakan lihat pembaruan saya. Bagaimana Anda menerapkannya, perhatikan bahwa saya mendapatkan seluruh daftar item di init
Shlomi Schwartz
sangat keren, terima kasih untuk itu. Saya berharap ini adalah fitur bawaan NG
Shlomi Schwartz
3
Masalah dengan pendekatan ini adalah bahwa jika Anda menonton properti yang ditugaskan, Anda akan berakhir dengan spamming $ digest (satu per iterasi) ... Mungkin ada beberapa cara untuk menghindari ini?
Juho Vepsäläinen
1
Jika saya menonton objek pencarian dan console.log filteredItemssaya selalu mendapatkan data satu filter nanti. Ini bukan hasil dari filter yang baru saja diubah, tetapi yang dari perubahan sebelumnya. Ada ide?
ProblemsOfSumit
4
Adakah yang bisa menjelaskan kepada saya, mengapa ini berhasil? Saya bisa mengerti bahwa variabel dari $ scope, dapat diakses di scope repeat (scope inheritance), tetapi sebaliknya? Bagaimana? Beberapa dokumentasi dihargai. Terima kasih
dalvarezmartinez1
30

Inilah versi filter dari solusi Andy Joslin.

Pembaruan: BREAKING CHANGE. Pada versi 1.3.0-beta.19 ( komitmen ini ) filter tidak memiliki konteks dan thisakan terikat pada cakupan global. Anda bisa meneruskan konteks sebagai argumen atau menggunakan sintaks aliasing baru di ngRepeat , 1.3.0-beta.17 +.

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

Kemudian menurut Anda

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

Yang memberi Anda akses ke $scope.filteredItems.

kevinjamesus86
sumber
Terima kasih! Bisakah Anda menjelaskan cara kerja kode filter? Saya tidak terbiasa dengan $ parse, dan dokumen sudut tidak membantu saya memecahkan kode cara kerja filter Anda.
Magne
2
@Magne Tidak masalah! Silakan periksa pembaruan meskipun karena dapat menyelamatkan Anda dari rasa sakit dan penderitaan di jalan. Untuk menjawab pertanyaan Anda, singkatnya, $parseadalah kompiler ekspresi Angular .. Sebagai contoh, ia akan mengambil string 'some.object.property' dan mengembalikan fungsi yang memungkinkan Anda untuk menetapkan atau mendapatkan nilai pada jalur tersebut untuk suatu yang ditentukan konteks. Saya menggunakannya untuk mengatur hasil filter pada $ scope di sini, khususnya. Saya harap ini menjawab pertanyaan Anda.
kevinjamesus86
23

Coba sesuatu seperti ini, masalah dengan ng-repeat adalah ia menciptakan lingkup anak karena itu Anda tidak dapat mengakses

filteritem

dari controller

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

Memperbarui:

Bahkan setelah 1.3.0. jika Anda ingin meletakkannya di lingkup controller atau orang tua Anda tidak dapat melakukannya dengan sebagai sintaks. Sebagai contoh jika saya memiliki kode berikut:

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

di atas tidak akan berfungsi. Cara mengatasinya menggunakan $ parent sebagai berikut:

<li ng-repeat="label in ($parent.labelResults = (labels | filter:query))">
Gal Bracha
sumber
Baik untuk dicatat bahwa jika Anda memiliki batas untuk memfilter ini. Ini tidak akan tercermin dalam $ parent.labelResults
Zack
Jika saya, console.log labelResultssaya selalu mendapatkan data satu filter nanti. Ini bukan hasil dari filter yang baru saja diubah, tetapi yang dari perubahan sebelumnya. Apakah kamu tidak memiliki masalah ini?
Anna
10

Saya datang dengan versi yang lebih baik dari solusi Andy. Dalam solusinya ng-repeat menempatkan arloji pada ekspresi yang berisi tugas. Setiap loop digest akan mengevaluasi ekspresi itu dan menetapkan hasilnya ke variabel lingkup.

Masalah dengan solusi ini adalah bahwa Anda mungkin mengalami masalah penugasan jika Anda berada dalam lingkup anak. Ini adalah alasan yang sama mengapa Anda harus memiliki titik dalam model ng .

Hal lain yang saya tidak suka tentang solusi ini adalah bahwa ia mengubur definisi array yang difilter di suatu tempat di tampilan markup. Jika digunakan di banyak tempat di tampilan Anda atau controller Anda, itu bisa membingungkan.

Solusi yang lebih sederhana adalah dengan hanya menempatkan jam di pengontrol Anda pada fungsi yang membuat tugas:

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

Fungsi ini akan dievaluasi selama setiap siklus cerna sehingga kinerja harus sebanding dengan solusi Andy. Anda juga dapat menambahkan sejumlah tugas dalam fungsi untuk menjaga semuanya di satu tempat daripada tersebar tentang tampilan.

Dalam tampilan, Anda hanya akan menggunakan daftar yang difilter secara langsung:

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

Inilah biola di mana ini ditampilkan dalam skenario yang lebih rumit.

Dave Johnson
sumber
Super bersih dan tidak mencemari struktur, bagus!
kuzyn
solusi ini sangat cocok untuk saya..saya menggunakan koleksi pengulangan ionik alih-alih ngulang..tapi mengapa jawaban yang diterima tidak bekerja untuk saya
Lakshay