AngularJS ng-repeat没有html元素

时间:2012-10-12 11:05:31

标签: javascript html css html5 angularjs

我目前正在使用这段代码来呈现一个列表:

<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>元素在某些浏览器上导致一些非常轻微的渲染缺陷。 我想知道有没有办法在没有div容器的情况下进行ng-repeat,或者有一些替​​代方法来实现相同的效果。

7 个答案:

答案 0 :(得分:103)

正如Andy Joslin所说,他们正致力于基于评论的ng-repeats but apparently there were too many browser issues。幸运的是,AngularJS 1.2增加了内置的重复支持,无需使用新指令ng-repeat-startng-repeat-end添加子元素。

以下是添加Bootstrap pagination的一个小例子:

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

可以找到一个完整的工作示例here

John Lindquist也有video tutorial of this over at his excellent egghead.io page

答案 1 :(得分:30)

KnockoutJS无容器绑定语法

请耐心等一下:KnockoutJS为foreach绑定提供了一种使用无容器绑定语法的超便捷选项,如foreach绑定文档的注释4中所述。 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-startng-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-startng-repeat-end

的更简洁方法

在调查hitautodestruct的断言后,将ng-repeat-end添加到单独的标记上正是我在大多数情况下想要做的事情,因为它会生成完全无用的元素:在这种情况下,<li>项目中没有任何内容。 Bootstrap 3的分页列表对列表项进行样式设置,使得它看起来不会生成任何多余的项,但是当您检查生成的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>

这有三个好处:

  1. 少写的html标签
  2. Angular
  3. 不会生成无用的空标签
  4. 当要重复的数组为空时,将不会生成带有ng-repeat的标记, 给你同样的优势Knockout的无容器装订为你提供了这方面的支持

  5. 但仍然有一种更清洁的方式

    在进一步审核github关于Angular这个问题的评论后,https://github.com/angular/angular.js/issues/1891
    您无需使用ng-repeat-startng-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-startng-repeat-end?根据{{​​3}},到

      

    ...重复一系列元素而不只是一个父元素......

    足够的谈话,展示一些例子!

    足够公平;这个jsbin通过五个例子来说明当你这样做以及在同一个标​​签上没有使用ng-repeat-end时会发生什么。

    angular documentation

答案 2 :(得分:6)

ngRepeat可能还不够,但您可以将其与自定义指令结合使用。如果你不介意一点jQuery,你可以委派将divider项添加到代码中的任务。

 <li ng-repeat="item in coll" so-add-divide="your exp here"></li>

这样一个简单的指令并不需要一个属性值,但可能会给你很多可能性,比如根据索引,长度等有条件地添加一个分隔符或者完全不同的东西。

答案 3 :(得分:3)

我最近遇到了同样的问题,因为我不得不重复一个任意的跨度和图像集合 - 周围有一个元素不是一个选项 - 但是,有一个简单的解决方案,创建一个“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元素,但再次检查它不会......仍然解决了我的布局问题,但是...好奇者和好奇者...

答案 4 :(得分:1)

有一个注释指令限制,但ngRepeat不支持它(因为它需要重复一个元素)。

我想我看到有角度的团队说他们会继续评论重复评论,但我不确定。您应该在回购中为它打开一个问题。 http://github.com/angular/angular.js

答案 5 :(得分:0)

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

答案 6 :(得分:0)

提供真正可行的解决方案

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块,而不仅仅是一个元素。 / p>

然后,定制remove指令将<remove>的开始和结束元素置于<!--removed element-->