AngularJS ng-repeat без элемента html
В настоящее время я использую этот фрагмент кода для отображения списка:
<ul ng-cloak>
<div ng-repeat="n in list">
<li><a href="{{ n[1] }}">{{ n[0] }}</a></li>
<li class="divider"></i>
</div>
<li>Additional item</li>
</ul>
Однако элемент <div>
вызывает некоторые незначительные дефекты рендеринга в некоторых браузерах.
Я хотел бы знать, есть ли способ выполнить ng-repeat без контейнера div или какой-либо альтернативный метод для достижения того же эффекта.
Ответы
Ответ 1
Как сказал Энди Хослин, они работали над ng-повторами на основе комментариев но, видимо, было слишком много проблем с браузером. К счастью, AngularJS 1.2 добавляет встроенную поддержку для повторения без добавления дочерних элементов с новыми директивами ng-repeat-start
и ng-repeat-end
.
Вот небольшой пример добавления Образец разбиения на страницы:
<ul class="pagination">
<li>
<a href="#">«</a>
</li>
<li ng-repeat-start="page in [1,2,3,4,5,6]"><a href="#">{{page}}</a></li>
<li ng-repeat-end class="divider"></li>
<li>
<a href="#">»</a>
</li>
</ul>
Здесь приведен полный рабочий пример здесь.
Джон Линдквист также имеет видеоурок об этом на своей превосходной странице egghead.io.
Ответ 2
Синтаксис привязки без надписей KnockoutJS
Пожалуйста, несите меня второй: KnockoutJS предлагает ультра-удобный вариант использования синтаксиса привязки без контейнера для привязки foreach
, как описано в примечании 4 к документации по привязке foreach
.
http://knockoutjs.com/documentation/foreach-binding.html
Как иллюстрирует пример документации Knockout, вы можете написать свою привязку в KnockoutJS следующим образом:
<ul>
<li class="header">Header item</li>
<!-- ko foreach: myItems -->
<li>Item <span data-bind="text: $data"></span></li>
<!-- /ko -->
</ul>
Я думаю, что это довольно неудачно. AngularJS не предлагает этот тип синтаксиса.
Angular ng-repeat-start
и ng-repeat-end
В методе AngularJS для решения проблем ng-repeat
образцы, с которыми я сталкиваюсь, относятся к типу jmagnusson, опубликованному в его (полезном) ответе.
<li ng-repeat-start="page in [1,2,3,4,5]"><a href="#">{{page}}</a></li>
<li ng-repeat-end></li>
Моя оригинальная мысль, увидев этот синтаксис: действительно? Почему Angular заставляет всю эту дополнительную разметку, с которой я не хочу иметь ничего общего, и это намного проще в Knockout? Но затем комментарий hitautodestruct в ответ jmagnusson начал заставлять меня задаться вопросом: что генерируется с помощью ng-repeat-start и ng-repeat-end в отдельных тегах?
Более чистый способ использования ng-repeat-start
и ng-repeat-end
При исследовании утверждения hitautodestruct добавление ng-repeat-end
к отдельному тегу - это именно то, что я хотел бы не делать в большинстве случаев, потому что он генерирует совершенно бесполезные элементы: в этом случае <li>
элементы, в которых нет ничего. Bootstrap 3 paginated list стилирует элементы списка так, что похоже, что вы не генерировали лишних элементов, но когда вы проверяете сгенерированный html, они есть.
К счастью, вам не нужно много делать, чтобы иметь более чистое решение и меньшее количество html: просто поместите объявление ng-repeat-end
на тот же тег html, у которого есть ng-repeat-start
.
<ul class="pagination">
<li>
<a href="#">«</a>
</li>
<li ng-repeat-start="page in [1,2,3,4,5]" ng-repeat-end><a href="#"></a></li>
<li>
<a href="#">»</a>
</li>
</ul>
Это дает 3 преимущества:
- меньше html-тегов для записи
- бесполезные пустые теги не генерируются Angular
- когда массив для повторения пуст, тег
ng-repeat
не будет генерироваться,
давая вам то же преимущество. Ноутаут без тарелки дает вам в этом отношении.
Но есть еще более чистый способ
После дальнейшего рассмотрения комментариев в github по этой проблеме для Angular, https://github.com/angular/angular.js/issues/1891,
вам не нужно использовать ng-repeat-start
и ng-repeat-end
для достижения тех же преимуществ.
Вместо этого, снова используя jmagnusson, мы можем просто пойти:
<ul class="pagination">
<li>
<a href="#">«</a>
</li>
<li ng-repeat="page in [1,2,3,4,5,6]"><a href="#">{{page}}</a></li>
<li>
<a href="#">»</a>
</li>
</ul>
Итак, когда использовать ng-repeat-start
и ng-repeat-end
? Согласно Angular документации,
... повторите серию элементов, а не только один родительский элемент...
Достаточно поговорить, показать несколько примеров!
Достаточно честный; этот jsbin просматривает пять примеров того, что происходит, когда вы делаете, и когда вы не используете ng-repeat-end
в том же теге.
Ответ 3
ngRepeat может быть недостаточно, однако вы можете комбинировать его с пользовательской директивой. Вы можете делегировать задачу добавления элементов делителя в код, если вы не против немного jQuery.
<li ng-repeat="item in coll" so-add-divide="your exp here"></li>
Такая простая директива действительно не требует значения атрибута, но может дать вам множество возможностей, таких как условное добавление разделителя в соответствии с индексом, длиной и т.д. или что-то совершенно другое.
Ответ 4
Недавно у меня была такая же проблема, что мне пришлось повторять произвольный набор пролетов и изображений - наличие элемента вокруг них не было возможным - там простое решение, однако, создайте директиву "null":
app.directive("diNull", function() {
return {
restrict: "E",
replace: true,
template: ""
};
});
Затем вы можете использовать повтор на этом элементе, где element.url указывает на шаблон для этого элемента:
<di-null ng-repeat="element in elements" ng-include="element.url" ></di-null>
Это повторит любое количество различных шаблонов без контейнера вокруг них
Примечание: хмм, я мог бы поклясться, что он удалил элемент di-null при рендеринге, но, проверяя его снова, он не... все еще решил мои проблемы с макетом, хотя... куриозер и куриозер...
Ответ 5
Существует ограничение на ограничение комментариев, но ngRepeat не поддерживает его (так как ему нужен элемент для повторения).
Я думаю, что увидел, что команда angular говорит, что они будут работать над комментариями ng-repeat, но я не уверен. Вы должны открыть для него проблему на репо. http://github.com/angular/angular.js
Ответ 6
Нет волшебного способа Angular для этого, для вашего случая вы можете это сделать, чтобы получить допустимый HTML, если вы используете Bootstrap. Тогда вы получите тот же эффект, что и добавление li.divider
Создать класс:
span.divider {
display: block;
}
Теперь измените свой код на это:
<ul ng-cloak>
<li div ng-repeat="n in list">
<a href="{{ n[1] }}">{{ n[0] }}</a>
<span class="divider"></span>
</li>
<li>Additional item</li>
</ul>
Ответ 7
для решения, которое действительно работает
HTML
<remove ng-repeat-start="itemGroup in Groups" ></remove>
html stuff in here including inner repeating loops if you want
<remove ng-repeat-end></remove>
добавить директиву angular.js
//remove directive
(function(){
var remove = function(){
return {
restrict: "E",
replace: true,
link: function(scope, element, attrs, controller){
element.replaceWith('<!--removed element-->');
}
};
};
var module = angular.module("app" );
module.directive('remove', [remove]);
}());
для краткого объяснения,
ng-repeat связывается с элементом <remove>
и выполняет циклы, как и должно быть, и поскольку мы использовали ng-repeat-start/ng-repeat-end, он циклически повторяет блок html, а не просто элемент.
затем пользовательская директива удаления помещает начальный и конечный элементы <remove>
<!--removed element-->