Ü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

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

Vucalur
quelle
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.

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

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

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