Übergeben von 2 $ Indexwerten innerhalb der verschachtelten ng-Wiederholung


322

Ich habe also eine ng-Wiederholung in einer anderen ng-Wiederholung verschachtelt, um ein Navigationsmenü zu erstellen. Auf jeder <li>in der inneren ng-repeat-Schleife setze ich einen ng-Klick, der den entsprechenden Controller für diesen Menüpunkt aufruft, indem ich den $ -Index übergebe, um der App mitzuteilen, welchen wir benötigen. Ich muss jedoch auch den $ -Index aus der äußeren ng-Wiederholung übergeben, damit die App weiß, in welchem ​​Abschnitt wir uns befinden und in welchem ​​Tutorial.

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

Hier ist ein Plunker http://plnkr.co/edit/bJUhI9oGEQIql9tahIJN?p=preview


Warum möchten Sie $ index übergeben? Übergeben Sie einfach die Objektreferenz wie folgt ng-click="loadFromMenu(section)". Wenn Sie $ index übergeben, führen Sie eine Schleife durch, um das nicht benötigte Objekt zu finden.
Moshii

Antworten:


467

Jede ng-Wiederholung erstellt einen untergeordneten Bereich mit den übergebenen Daten und fügt diesem Bereich eine zusätzliche $indexVariable hinzu .

Was Sie also tun müssen, ist, den übergeordneten Bereich zu erreichen und diesen zu verwenden $index.

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

Genial, so greife ich auf den äußeren $ Index zu, aber ich musste BEIDE $ Indexwerte übergeben. Ich habe versucht, sie in ein Array zu setzen und es hat funktioniert :)
Tules

16
Sie müssen kein Array verwenden: ng-click="loadFromMenu($parent.$index, $index)"
Mark Rajcok

3
Sie müssen nicht einmal die Indizes übergeben - im loadFromMenu sollte es Zugriff auf dieses Objekt haben, wodurch Sie Zugriff auf
Folgendes erhalten

3
@Oddman, obwohl dies möglich ist, halte ich es nicht für eine gute Idee, wenn Sie dann Ihr loadFromMenu fest verdrahten, um es in einem Kontext eines Objekts auszuführen, das einen Bereich mit einem $ index und einen übergeordneten Bereich mit einem $ index hat. Angenommen, Sie erstellen dann beispielsweise Gruppen innerhalb des Menüs, die einen anderen Bereich zwischen den beiden signifikanten generieren. Sie müssen loadFromMenu ändern, anstatt den Aufruf zu ändern. Und wenn Sie in einigen Menüs anrufen müssen loadFromMenu($parent.$parent.$index,$index)und in einigen, die Sie gerade brauchen loadFromMenu($parent.$index,$index), this....würde die Verwendung einfach nicht funktionieren.
Epeleg

7
Sie sollten $ parent. $ Index nicht verwenden, da dies nicht wirklich sicher ist. Wenn Sie ein ng-if innerhalb der Schleife hinzufügen, wird der $ index durcheinander gebracht. Überprüfen Sie: plnkr.co/52oIhLfeXXI9ZAynTuAJ
gonzalon

201

Viel elegantere Lösung als $parent.$indexverwendet 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
Dies ist die empfohlene Methode, um diesen Effekt zu erzielen. Tatsächlich hat das Angular-Team einige Male zum Ausdruck gebracht, dass dies eine der wenigen empfohlenen Anwendungen der ng-init-Direktive ist (siehe: Link ). Ich finde oft, dass die Verwendung von $ parent (gemäß der derzeit akzeptierten Antwort) ein bisschen nach Code riecht, da es normalerweise eine bessere Möglichkeit gibt, die Kommunikation von $ scope zu $ ​​scope (Dienste oder Broadcast / Emit-Ereignisse) zu erreichen und sie einem zuzuweisen benannte Variable wird klarer, was der Wert darstellt.
David Beech

2
IMO ist diese Antwort viel besser als die akzeptierte. Die Verwendung von $ parent ist wirklich, wirklich nicht ratsam.
Olivarra1

43
Dies funktioniert nicht mehr, wenn Sie Elemente aus der Liste entfernen, da der ng-init-Wert nicht neu initialisiert wird. Dies ist nur nützlich, wenn Sie keine Elemente aus der Liste entfernen möchten.
Jesse Greathouse

6
Sieht aus wie sich die Winkelsyntax entwickelt hat. stackoverflow.com/a/31477492/2516560 Sie können jetzt "ng-repeat = (Schlüssel, Wert) in Daten" verwenden
Okazari

2
Damals, als ich diese Antwort schrieb, war dies der Weg, dies für Angular 1.X zu tun. Diese Verwendung von ng-initwurde in ng-initDokumenten demonstriert, ohne dass dies in Dokumenten erwähnt wurde. ng-repeatDeshalb habe ich hier geschrieben und die Dokumente auf Github geändert. Die aktuelle ng-repeatSyntax bietet einen besseren Weg, um dies zu erreichen, was @Okazari demonstriert. Es ist frei von einigen Mängeln, die Sie in den Kommentaren erwähnt haben.
Vucalur

115

Was ist mit dieser Syntax (werfen Sie einen Blick in diesen Plunker ). Ich habe das gerade entdeckt und es ist ziemlich großartig.

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

Beispiel:

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

Mit dieser Syntax können Sie $indexden beiden Indizes Ihren eigenen Namen geben und sie unterscheiden.


8
Ich denke, das ist viel sauberer als die Verwendung von Eltern, wenn Sie mehrere verschachtelte Schleifen haben
Yasitha Chinthaka

Tatsächlich verursachte dies einige echte Probleme bei der Verwendung des Winkel-UI-Baums zum Ziehen / Ablegen von Knoten. Der Index scheint nicht zurückgesetzt zu werden und es passieren seltsame Dinge.
Mike Taverne

@ MikeTaverne Könnten Sie versuchen, sich in einem Plunker zu reproduzieren? Ich würde das Verhalten gerne sehen.
Okazari

4
Dies ist der richtige Weg, um dies zu erreichen und mögliche Probleme zu vermeiden. ng-init funktioniert beim ersten Rendern, aber wenn das Objekt auf der Seite aktualisiert wird, bricht es.
Eric Martin

gut! Aber bitte korrigieren Sie dies durch Hinzufügen von "Track by" wie im Plunker-Beispiel.
Danilo

32

Nur um jemandem zu helfen, der hierher kommt ... Sie sollten nicht $ parent. $ Index verwenden, da dies nicht wirklich sicher ist. Wenn Sie ein ng-if in die Schleife einfügen, wird der $ index durcheinander gebracht!

Richtiger Weg

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

Überprüfen Sie: plnkr.co/52oIhLfeXXI9ZAynTuAJ


Beachten Sie, dass das "Verfolgen von" hier nicht benötigt wird - dies ist eine separate Funktion, die für ng-repeat verwendet wird, um eindeutige Elemente zu verstehen und auf Änderungen in der Sammlung zu achten (siehe Abschnitt "Verfolgen und Duplizieren" in den Dokumenten: docs.angularjs.org / api / ng / directive / ngRepeat ). Der wichtige Punkt hier ist das "ng-init" - das ist die richtige Art und Weise, mit der die eckigen Dokumente übereinstimmen.
Rebecca

@gonzalon Wie man diesen Index als Parameter in ng click übergibt
Nagaraj S

Ich mache removeList ($ index) oder removeList (rowIndex). Der Index wird in der Funktion, in der ich den Indexwert als undefiniert erhalte, nicht korrekt aufgezeichnet. Ich benutze Winkel 1.5.6
user269867

Dies ist der richtige Weg, Sie sollten niemals auf $ parent zugreifen
Jesú Castillo

3

Wenn Sie mit Objekten arbeiten, möchten Sie einfache IDs so weit wie möglich ignorieren.

Wenn Sie die Klicklinie in diese ändern, sind Sie auf einem guten Weg:

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

Ich denke auch, dass Sie sich möglicherweise ändern müssen

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

zu so etwas wie

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

Siehe http://docs.angularjs.org/misc/faq und suchen Sie nach ng-class.


1

Benutz einfach ng-repeat="(sectionIndex, section) in sections"

und das wird auf der nächsten Ebene verwendbar sein 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>
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.