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="#">&laquo;</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="#">&raquo;</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="#">&laquo;</a>
  </li>    
  <li ng-repeat-start="page in [1,2,3,4,5]" ng-repeat-end><a href="#"></a></li>
  <li>
    <a href="#">&raquo;</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="#">&laquo;</a>
  </li>
  <li ng-repeat="page in [1,2,3,4,5,6]"><a href="#">{{page}}</a></li>
  <li>
    <a href="#">&raquo;</a>
  </li>
</ul>

Итак, когда использовать ng-repeat-start и ng-repeat-end? Согласно Angular документации,

... повторите серию элементов, а не только один родительский элемент...

Достаточно поговорить, показать несколько примеров!

Достаточно честный; этот jsbin просматривает пять примеров того, что происходит, когда вы делаете, и когда вы не используете ng-repeat-end в том же теге.

http://jsbin.com/eXaPibI/1/

Ответ 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-->