melewati 2 $ nilai indeks dalam nested ng-repeat


322

Jadi saya punya ng-repeat yang bersarang di ng-repeat lain untuk membangun menu nav. Pada masing-masing <li>di loop berulang ng-dalam saya menetapkan ng-klik yang memanggil controller yang relevan untuk item menu dengan melewati indeks $ untuk membiarkan aplikasi tahu mana yang kita butuhkan. Namun saya juga harus lulus dalam indeks $ dari luar ng-repeat sehingga aplikasi tahu bagian mana kita dan tutorial yang mana.

<ul ng-repeat="section in sections">
    <li  class="section_title {{section.active}}" >
        {{section.name}}
    </li>
    <ul>
        <li class="tutorial_title {{tutorial.active}}" ng-click="loadFromMenu($index)" ng-repeat="tutorial in section.tutorials">
            {{tutorial.name}}
        </li>
    </ul>
</ul>

inilah Plunker http://plnkr.co/edit/bJUhI9oGEQIql9tahIJN?p=preview


Mengapa Anda ingin melewati $ index? cukup lewati referensi objek seperti ini ng-click="loadFromMenu(section)". Melewati $ index berarti Anda akan melakukan loop untuk menemukan objek yang tidak perlu.
— Moshii

Jawaban:


468

Setiap ng-repeat membuat lingkup anak dengan data yang dikirimkan, dan juga menambahkan $indexvariabel tambahan dalam lingkup itu.

Jadi yang perlu Anda lakukan adalah menjangkau hingga lingkup induk, dan menggunakannya $index.

Lihat http://plnkr.co/edit/FvVhirpoOF8TYnIVygE6?p=preview

<li class="tutorial_title {{tutorial.active}}" ng-click="loadFromMenu($parent.$index)" ng-repeat="tutorial in section.tutorials">
    {{tutorial.name}}
</li>

mengagumkan, jadi itulah cara saya mengakses indeks luar $, tapi saya harus memasukkan nilai KEDUA $ indeks. Saya mencoba menempatkan mereka dalam sebuah array dan berhasil :)
— Tules

16
Anda tidak harus menggunakan array: ng-click="loadFromMenu($parent.$index, $index)"
— Mark Rajcok

3
Anda bahkan tidak harus meneruskan indeks - di loadFromMenu, ia harus memiliki akses ke objek ini, yang akan memberi Anda akses ke: this. $ index dan this. $ parent. $ index
— Oddman

3
@Oddman meskipun ini mungkin saya tidak berpikir itu ide yang baik karena Anda kemudian memasang kawat loadFromMenu Anda untuk dijalankan pada konteks objek yang memiliki lingkup dengan indeks $ dan lingkup induk dengan indeks $. misalkan Anda misalnya membuat grup di dalam menu yang menghasilkan ruang lingkup lain di antara dua yang signifikan - Anda harus mengubah loadFromMenu alih-alih mengubah panggilan ke sana. Dan jika dalam beberapa menu Anda perlu menelepon loadFromMenu($parent.$parent.$index,$index)dan dalam beberapa Anda hanya perlu loadFromMenu($parent.$index,$index)menggunakan tidak this....akan bekerja.
— epeleg

7
Anda tidak boleh menggunakan $ parent. $ Index karena itu tidak benar-benar aman. Jika Anda menambahkan ng-jika di dalam loop, Anda mendapatkan $ index berantakan, periksa: plnkr.co/52oIhLfeXXI9ZAynTuAJ
— gonzalon

201

Solusi yang jauh lebih elegan daripada $parent.$indexmenggunakan ng-init:

<ul ng-repeat="section in sections" ng-init="sectionIndex = $index">
    <li  class="section_title {{section.active}}" >
        {{section.name}}
    </li>
    <ul>
        <li class="tutorial_title {{tutorial.active}}" ng-click="loadFromMenu(sectionIndex)" ng-repeat="tutorial in section.tutorials">
            {{tutorial.name}}
        </li>
    </ul>
</ul>

Plunker: http://plnkr.co/edit/knwGEnOsAWLhLieKVItS?p=info


2
Ini adalah metode yang direkomendasikan untuk mencapai efek ini. Sebenarnya tim sudut telah menyatakan beberapa kali bahwa ini adalah salah satu dari beberapa kegunaan yang disarankan dari arahan ng-init (lihat: tautan ). Saya sering menemukan penggunaan $ parent (sesuai jawaban yang saat ini diterima) adalah sedikit bau kode karena biasanya ada cara yang lebih baik untuk mencapai $ scope ke $ scope komunikasi (Layanan atau Siaran / Emit Events) dan dengan menugaskannya ke variabel bernama itu menjadi lebih jelas apa yang mewakili nilai.
— David Beech

2
IMO jawaban ini jauh lebih baik daripada yang diterima. Menggunakan $ parent benar-benar tidak disarankan.
— olivarra1

43
Ini berhenti berfungsi ketika Anda menghapus item dari daftar karena nilai ng-init tidak menginisialisasi ulang. Ini hanya berguna jika Anda tidak bermaksud untuk menghapus item dari daftar.
— Jesse Greathouse

6
Sepertinya sintaksis sudut berevolusi. stackoverflow.com/a/31477492/2516560 sekarang Anda dapat menggunakan "ng-repeat = (key, value) dalam data"
— Okazari

2
Kembali pada hari-hari kemudian saya menulis jawaban ini, ini adalah cara untuk melakukannya untuk Angular 1.X. Penggunaan ng-initini ditunjukkan dalam ng-initdokumen tanpa menyebutkan ng-repeatdokumen, jadi saya menulis di sini + mengubah dokumen di Github. ng-repeatSintaksis saat ini memiliki cara yang lebih baik untuk mencapai hal ini, yang ditunjukkan oleh @Okazari. Ini bebas dari beberapa ketidaksempurnaan yang disebutkan oleh Anda dalam komentar.
— vucalur

115

Bagaimana dengan menggunakan sintaks ini (lihat di plunker ini ). Saya baru saja menemukan ini dan itu sangat mengagumkan.

ng-repeat="(key,value) in data"

Contoh:

<div ng-repeat="(indexX,object) in data">
    <div ng-repeat="(indexY,value) in object">
       {{indexX}} - {{indexY}} - {{value}}
    </div>
</div>

Dengan sintaks ini Anda dapat memberikan nama Anda sendiri $indexdan membedakan dua indeks.


8
Saya pikir ini jauh lebih bersih daripada menggunakan orang tua ketika Anda memiliki beberapa loop bersarang
— Yasitha Waduge

Sebenarnya ini menyebabkan saya beberapa masalah nyata ketika menggunakan angular-ui-tree untuk drag / drop node. Indeks sepertinya tidak mendapatkan reset dan hal-hal aneh terjadi sebagai hasilnya.
— Mike Taverne

@ MikeTaverne Bisakah Anda mencoba mereproduksi dalam plunker? Saya ingin sekali melihat perilakunya.
— Okazari

4
Ini adalah cara yang tepat untuk mencapai ini dan menghindari potensi masalah. ng-init berfungsi untuk render awal, tetapi jika objek diperbarui pada halaman, itu rusak.
— Eric Martin

baik! tapi tolong perbaiki dengan menambahkan "track by" seperti contoh plunker.
— Danilo

32

Hanya untuk membantu seseorang yang datang ke sini ... Anda tidak boleh menggunakan $ parent. $ Index karena itu tidak benar-benar aman. Jika Anda menambahkan ng-jika di dalam loop, Anda mendapatkan $ index berantakan!

Cara yang benar

  <table>
    <tr ng-repeat="row in rows track by $index" ng-init="rowIndex = $index">
        <td ng-repeat="column in columns track by $index" ng-init="columnIndex = $index">

          <b ng-if="rowIndex == columnIndex">[{{rowIndex}} - {{columnIndex}}]</b>
          <small ng-if="rowIndex != columnIndex">[{{rowIndex}} - {{columnIndex}}]</small>

        </td>
    </tr>
  </table>

Periksa: plnkr.co/52oIhLfeXXI9ZAynTuAJ


Perhatikan bahwa "lacak oleh" tidak diperlukan di sini - itu adalah hal terpisah yang digunakan untuk ng-repeat untuk memahami item unik dan melihat perubahan dalam koleksi (lihat bagian "Melacak dan Duplikat" dari dokumen: docs.angularjs.org / api / ng / directive / ngReat ). Poin penting di sini adalah "ng-init" - itu adalah cara yang benar yang disetujui oleh dokumen sudut.
— Rebecca

@gonzalon Cara meneruskan indeks ini sebagai parameter dalam ng klik
— Nagaraj S

Saya sedang melakukan removeList ($ index) atau removeList (rowIndex) Ini tidak mencatat indeks dengan benar dalam fungsi saya menerima nilai indeks sebagai tidak terdefinisi. Saya menggunakan sudut 1.5.6
— user269867

Ini adalah cara yang benar, Anda seharusnya tidak pernah mengakses $ parent
— Jesú Castillo

3

Ketika Anda berhadapan dengan objek, Anda ingin mengabaikan id sederhana sebanyak yang nyaman.

Jika Anda mengubah baris klik ke ini, saya pikir Anda akan berada di jalan:

<li class="tutorial_title {{tutorial.active}}" ng-click="loadFromMenu(tutorial)" ng-repeat="tutorial in section.tutorials">

Juga, saya pikir Anda mungkin perlu berubah

class="tutorial_title {{tutorial.active}}"

untuk sesuatu seperti

ng-class="tutorial_title {{tutorial.active}}"

Lihat http://docs.angularjs.org/misc/faq dan cari ng-class.


1

Gunakan saja ng-repeat="(sectionIndex, section) in sections"

dan itu akan bisa digunakan pada level selanjutnya ng-repeat down.

<ul ng-repeat="(sectionIndex, section) in sections">
    <li  class="section_title {{section.active}}" >
        {{section.name}}
    </li>
    <ul>
        <li ng-repeat="tutorial in section.tutorials">
            {{tutorial.name}}, Your section index is {{sectionIndex}}
        </li>
    </ul>
</ul>
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.