передача значень 2 $ в межах вкладеного ng-повтору


322

Таким чином, я маю ng-повторення вкладене в інший ng-повтор, щоб створити меню nav. На кожному <li>внутрішньому циклі ng-повторів я встановлюю клавішу ng, яка викликає відповідний контролер для цього пункту меню, передаючи $ index, щоб програма могла знати, який нам потрібен. Однак мені також потрібно передати індекс $ від зовнішнього ng-повтору, щоб програма знала, у якому розділі ми знаходимось, а також у якому підручнику.

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

ось Plunker http://plnkr.co/edit/bJUhI9oGEQIql9tahIJN?p=preview


Чому ви хочете передати $ index? просто передайте посилання на об'єкт так ng-click="loadFromMenu(section)". Передача $ index означає, що ви зробите цикл, щоб знайти непотрібний об'єкт.
— Мошій

Відповіді:


468

Кожне ng-повторення створює дочірню область з переданими даними, а також додає додаткову $indexзмінну в цій області.

Тож те, що вам потрібно зробити, - це охопити батьківські рамки, і використовувати це $index.

Дивіться 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>

дивним, тому я отримую доступ до зовнішнього $ індексу, але мені потрібно було передати значення BOTH $ index. Я спробував поставити їх у масив, і це спрацювало :)
— Tules

16
Вам не доведеться використовувати масив: ng-click="loadFromMenu($parent.$index, $index)"
— Марк Райкок

3
вам навіть не потрібно передавати індекси - у loadFromMenu він повинен мати доступ до цього об’єкта, який надасть вам доступ до: цього. $ індексу та цього. $ батьківського. $ індексу
— Oddman

3
@Oddman, хоча це можливо, я не думаю, що це гарна ідея, оскільки ви потім жорстко проводите ваш loadFromMenu для запуску в контексті об'єкта, який має область з індексом $ і батьківський діапазон з індексом $. припустимо, ви, наприклад, створюєте групи в меню, які генерують іншу область між двома значущими - вам доведеться змінити loadFromMenu замість того, щоб змінювати виклик до нього. І якщо в деяких меню вам потрібно зателефонувати, loadFromMenu($parent.$parent.$index,$index)а в деяких вам просто loadFromMenu($parent.$index,$index)тоді використання this....просто не вийшло.
— epeleg

7
Не слід використовувати $ parent. $ Index, оскільки це не дуже безпечно. Якщо ви додасте ng-if всередині циклу, ви отримаєте $ index messed
— gonzalon

201

Шлях більш елегантне рішення, ніж $parent.$indexвикористання 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
Це рекомендований метод досягнення цього ефекту. Насправді кутова команда кілька разів висловлювала думку, що це одне з небагатьох рекомендованих застосувань директиви ng-init (див. Посилання ). Я часто знаходжу використання $ parent (відповідно до прийнятої на даний момент відповіді) - це трохи запах коду, оскільки зазвичай є кращий спосіб досягнення $ range до комунікації $ range (Послуги або трансляція / випромінювання подій) і присвоюючи його з назвою змінної, стає зрозуміліше, що представляє значення.
— Девід Бук

2
ІМО ця відповідь набагато краща за прийняту. Використання $ parent - це дійсно, дуже без уваги.
— olivarra1

43
Це припиняє роботу, коли ви вилучаєте елементи зі списку, оскільки значення ng-init не ініціалізується. Це корисно, лише якщо ви не маєте наміру видаляти елементи зі списку.
— Джессі Грейтхаус

6
Схоже, що розвинувся кутовий синтаксис. stackoverflow.com/a/31477492/2516560 тепер ви можете використовувати "ng-repe = = (ключ, значення) в даних"
— Okazari

2
Ще в ті часи, коли я писав цю відповідь, це був спосіб зробити це для Angular 1.X. Це використання ng-initбуло продемонстровано в ng-initдокументах без жодної згадки в ng-repeatдокументах, тому я писав тут + виправляв документи на Github. Поточний ng-repeatсинтаксис має кращий спосіб досягти цього, що демонструє @Okazari. Це не містить деяких недосконалостей, згаданих вами в коментарях.
— вукалур

115

Як щодо використання цього синтаксису (дивіться у цьому планку ). Я щойно це виявив, і це досить приголомшливо.

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

Приклад:

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

За допомогою цього синтаксису ви можете дати власне ім’я $indexта диференціювати два індекси.


8
Я думаю, що це набагато чистіше, ніж використання батьків, коли у вас є кілька вкладених циклів
— Yasitha Chinthaka

Насправді це викликало у мене справжні проблеми при використанні angular-ui-tree для перетягування вузлів. Схоже, індекс не обнуляється, і в результаті відбуваються дивні речі.
— Майк Таверн

@MikeTaverne Чи можете ви спробувати відтворити в планку? Я хотів би побачити поведінку.
— Оказарі

4
Це правильний спосіб досягти цього і уникнути можливих проблем. ng-init працює для початкового візуалізації, але якщо об’єкт оновлено на сторінці, він ламається.
— Ерік Мартін

добре! але, будь ласка, виправте додавання "доріжки", як приклад планера.
— Данило

32

Просто, щоб допомогти тому, хто потрапить сюди ... Не слід використовувати $ parent. $ Index, оскільки це не дуже безпечно. Якщо ви додасте ng-if всередині циклу, ви отримаєте $ index messed!

Правильний шлях

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

Перевірте: plnkr.co/52oIhLfeXXI9ZAynTuAJ


Зауважте, що "доріжка" тут не потрібна - це окрема річ, яка використовується для ng-повторів для розуміння унікальних елементів та спостереження за змінами в колекції (див. Розділ "Відстеження та копії" в docs: docs.angularjs.org / api / ng / директива / ngRepeat ). Важливим моментом тут є "ng-init" - це правильний спосіб, з яким погоджуються кутові документи.
— Ребекка

@gonzalon Як передати цей індекс як параметр натисканням кнопки
— Nagaraj S

Я роблю removeList ($ index) або deleteList (rowIndex) Це не записує індекс правильно у функції, я отримую значення індексу як невизначене. Я використовую кутовий 1.5.6
— user269867

Це вірний спосіб, ви ніколи не повинні отримувати доступ до $ parent
— Jesú Castillo

3

Коли ви маєте справу з об’єктами, ви хочете ігнорувати прості ідентифікатори максимально зручно.

Якщо ви зміните рядок кліку на це, я думаю, ви будете добре на своєму шляху:

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

Також, я думаю, вам може знадобитися змінити

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

на щось подібне

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

Дивіться http://docs.angularjs.org/misc/faq і шукайте ng-class.


1

Просто використовуйте ng-repeat="(sectionIndex, section) in sections"

і це буде корисно на наступному рівні ng-повторення вниз.

<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>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.