передача значень 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.