ngRepeat — рабочая лошадка в шаблонах, используемых при работе с AngularJS. Цикл имеет множество опций, работает с фильтрами и сортировкой, может подключать части шаблона при наличии каких либо условий и т.д.
Здесь мы рассмотрим некоторые варианты использования ng-repeat, типовые шаблоны, не углубляюсь особо в описание параметров, методов. Подробно цикл описан в официальном руководстве.
В начале я приведу код шаблона и скрипта целиком, чтобы было понятно и прозрачно как это работает для всех, кто только разбирается с Angular. Их можно будет скачать и в виде архива. Далее я буду приводить только кусочки кода/шаблона с изменениями.
Вывод в цикле данных из контроллера
Это HTML файл:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<!doctype html> <html ng-app="projectRepDemo"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <script id="angularScript" src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script> <script src="/app-js/project.js"></script> </head> <body> <div ng-controller="ngRepDemo as rep"> <label>Список объектов:</label><br /> <ul> <li ng-repeat="elm in rep.list">{{elm.name}}</li> </ul> </div> </body> </html> |
JS код хранится в файле project.js. Там мы объявляем модуль projectRepDemo и описываем контроллер ngRepDemo.
1 2 3 4 5 6 7 8 9 10 11 |
angular.module('projectRepDemo', []) .constant('TANKS', [ {name: 'Леопард 2A7 (Германия)', speed: 72}, {name: 'M1A2 (США)', speed: 68}, {name: 'Challenger 2 (Великобритания)', speed: 59}, {name: 'Merkava Mark IV (Израиль)', speed: 64}, {name: 'Танк Т-90МС "Тагил"', speed: 60}] ) .controller('ngRepDemo', function (TANKS) { this.list = TANKS; }); |
В контроллере мы получаем массив данных из объявленной здесь же константы. ngRepeat выполняет работу в шаблоне по созданию списка.
Получаем в итоге:
Вывод в цикле данных без контроллера
Вообще-то контроллер нам пригодился бы для дву-направленной работы с данными, когда мы меняем что то в браузере, Angular может отслеживать связанные данные.
Т.е. для работы ngRepeat не нужен ни контроллер, ни константа объявленные в модуле.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<body> <div> <label>Список объектов:</label><br /> <ul> <li ng-repeat="elm in [ {name: 'Леопард 2A7 (Германия)', speed: 72}, {name: 'M1A2 (США)', speed: 68}, {name: 'Challenger 2 (Великобритания)', speed: 59}, {name: 'Merkava Mark IV (Израиль)', speed: 64}, {name: 'Танк Т-90МС Тагил', speed: 60}]">{{elm.name}}</li> </ul> </div> </body> |
Перебор свойств объекта в цикле ng-Repeat
При желании, можно перебирать не только элементы массива. Следующий синтаксис позволит «перебрать» свойства объекта:
1 |
<div ng-repeat="(key, value) in myObj"> ... </div> |
В примере выше выводится название танка, давайте выведем все свойства:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<div ng-controller="ngRepDemo as rep"> <label>Список объектов:</label><br /> <ul> <li ng-repeat="elm in rep.list"> Танк № {{$index}} <ul> <li ng-repeat="(key, value) in elm"> {{key}}: {{value}}, свойство № {{$index}} </li> </ul> </li> </ul> </div> |
Как получить итератор $index внешнего цикла в контексте внутреннего читайте вот тут.
Проверка условий внутри цикла ng-repeat
Для более качественной обработки цикл можно комбинировать с директивой ng-if. Выведем в первом и последнем элементе горизонтальную черту:
1 2 3 4 5 6 7 8 9 10 |
<div ng-controller="ngRepDemo as rep"> <label>Список объектов:</label><br /> <ul> <li ng-repeat="elm in rep.list"> <div ng-if="$first"><hr /></div> {{elm.name}} <div ng-if="$last"><hr /></div> </li> </ul> </div> |
$first и $last переменные в контексте цикла, сигнализируют, соответственно, что выполняется первая и последняя итерации цикла.
Использование фильтра в цикле
Добавим поле ввода в наш пример, чтобы получить динамический фильтр для списка наших, как выяснилось, танков:
1 2 3 4 5 6 7 8 9 |
<div ng-controller="ngRepDemo as rep"> <label>Список Танков:</label><br /> <input ng-model="s" placeholder="фильтр по названию..." /> <ul> <li ng-repeat="elm in rep.list | filter:s"> {{elm.name}} </li> </ul> </div> |
Мы использовали ещё одну директиву ng-model. Она нам нужна для связи с фильтром в ng-repeat.
Сортировка списка в ng-Repeat
Для сортировки списка используется расширение синтаксиса директивы ngRepeat оператором orderBy:
1 |
<span class="pln">item </span><span class="kwd">in</span><span class="pln"> items </span><span class="pun">|</span> <span class="pln">orderBy </span><span class="pun">:</span><span class="pln"> order </span> |
В самом простом случае мы указываем имя свойство элемента item, по которому производится сортировка.
Добавим сортировку по названию танка в наш фильтр:
1 2 3 4 5 6 7 |
<div ng-controller="ngRepDemo as rep"> <label>Список Танков:</label><br /> <input ng-model="s" placeholder="фильтр по названию..." /> <ul> <li ng-repeat="elm in rep.list | filter:s | orderBy:'name'">{{elm.name}}</li> </ul> </div> |
Для обратного порядка элементов (реверса) необходимо включить реверс (кыш-кыш, Кэп). Мы добавляем «true» после имени свойства в сортировке:
1 |
<li ng-repeat="elm in rep.list | filter:s | orderBy:'name':true">{{elm.name}}</li> |
В примерах выше используется встроенная функция сравнения. Но можно задать и кастомную функцию. Об этом лучше всего почитать в руководстве.
Ограничение числа элементов, выводимых циклом ngRepeat
Если элементов много, а нужно выводить лишь часть?
Можно обойтись уже старыми трюками, например, используя директиву ng-if. Ограничим вывод тремя элементами:
1 2 3 4 5 6 |
<div ng-controller="ngRepDemo as rep"> <label>Список Танков:</label><br /> <ul> <li ng-repeat="elm in rep.list" ng-if="$index < 3">{{elm.name}}</li> </ul> </div> |
Но разработчики заложили контроль числа элементов прямо в синтаксис директивы ng-repeat:
1 2 3 4 5 6 |
<div ng-controller="ngRepDemo as rep"> <label>Список Танков:</label><br /> <ul> <li ng-repeat="elm in rep.list | limitTo:3">{{elm.name}}</li> </ul> </div> |
Оба варианта покажут одно и тоже:
Возможности limitTo шире, чем демонстрируется в данном примере. Велкам ту офишал гайд.