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

Tules
sumber
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>
Alex Osborn
sumber
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

vucalur
sumber
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.

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

Gonzalon
sumber
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.

kwerle
sumber
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>
RobKohr
sumber