没有html元素的AngularJS ng-repeat


91

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

<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,或通过其他方法来达到相同的效果。


您在谈论什么渲染问题?
杰克

最后一个li分频器似乎有点像堆积的(chrome win7)。这可能是一个CSS问题,但是,我想知道是否可以固定角度。为了进行比较,knockoutJS允许使用<!-->进行无容器绑定。
nehz 2012年

我明白了,我用在服务器端PHPTAL,他们有一个TAL:块标记专门为此:)猜测与DOM并不总是接受一种新的广告代码,与角更难
杰克

您还可以更新html以反映您如何使用htmlAppend指令吗?
尼克

做...做过一段时间,但我确实记得它有效
nehz 2013年

Answers:


104

正如Andy Joslin所说,他们正在研究基于注释的ng-repeats,但显然存在太多浏览器问题。幸运的是,AngularJS 1.2添加了对重复的内置支持,而无需使用新的指令ng-repeat-start和添加子元素ng-repeat-end

这是添加Bootstrap分页的一个小示例:

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

一个完整的工作示例可以在这里找到。

John Lindquist 在其出色的egghead.io页面上有关于此视频教程


3
这不要求打印元素吗?
hitautodestruct

2
我对仅在[1,2,3,4,5,6]中的<li ng-repeat =“ page> > </ li> -edit:没关系,我想我明白了
Shadaez

6
我知道您只是在试图演示,ng-repeat-start/end但这是一个令人困惑的示例,并且用例不正确。ng-repeat这里应该使用一个标准,因为您的代码li为每个项目提供了一个额外的空白。您可能应该在您的帖子中提到这一点。
GFoley83 2014年

2
@ GFoley83你是正确的。但是他似乎想要每次迭代都需要额外的元素,而如果没有的话,这是不可能的ng-repeat-start。我将dividerhtml类添加到我的答案中以使其更加清晰。
jmagnusson

1
ng-repeat-start并且ng-repeat-end有点混乱。Angular文档可帮助:https
//docs.angularjs.org/api/ng/directive/ngRepeat#special-repeat-start-and-end-points

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不提供这种语法。


角的ng-repeat-startng-repeat-end

在解决ng-repeat问题的AngularJS方式中,我遇到的示例属于jmagnusson类型(在其有用的答案中)。

<li ng-repeat-start="page in [1,2,3,4,5]"><a href="#">{{page}}</a></li>
<li ng-repeat-end></li>

看到这种语法时,我的最初想法是:真的吗?为什么Angular会强制执行所有我不想使用的额外标记,而在淘汰赛中却如此简单呢?但是后来在jmagnusson的答案中hitautodestruct的评论让我感到疑惑:分别标记上的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>

这具有3个优点:

  1. 更少的HTML标签来写
  2. Angular不会生成无用的空标签
  3. 当要重复的数组为空时,ng-repeat不会生成带有的标签,为您提供相同的优势Knockout的无容器绑定在这方面为您提供了帮助

但是还有一种更清洁的方法

进一步审查关于这个问题的角度,在GitHub上的意见后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-startng-repeat-end?根据角度文件

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

聊够了,展示一些例子!

很公平; 该jsbin演示了五个示例,分别说明了您ng-repeat-end在同一标签上使用和不使用时会发生什么。

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


11
您似乎已经误解了问题的重点。目标是同时重复两个或多个列表项,您的示例和您链接的页面都没有提供实现此目的的方法。正如您已经指出的那样,当您可以使用angular的默认值并对其进行处理时,将ng-repeat-start和附加ng-repeat-end到同一元素上完全没有ng-repeat用。
Asad Saeeduddin 2014年

@Asad-OP并未明确指出“问题要点”。另外,您是否检查了接受答案的渲染DOM输出?我无法想象有人想要这样的输出,至少可以肯定没有自举分页列表。
mg1075 2014年

1
@ mg1075是的,接受的答案的输出是不可接受的,这就是为什么我一直向下滚动到这里。问题的重点很明确:找到一种方法来应用ng-repeat或找到OP使用方法的替代方法,ng-repeat从而消除div了HTML中的工件。您的答案不会这样做,因为无法将其用于问题中的两个li元素。如果我在这里错了,请提供示例标记,以适应OP的代码以消除该div元素。
Asad Saeeduddin

@Asad-如果OP提供了他想要的输出的完整示例,那么问题的重点会更加清楚。他接受“接受的”答案的事实(接受的答案使用带有实质上不正确标记的自举分页)只会使问题更加混乱。jsbin中的示例2(如果确实如此)可以通过已接受答案的方式解决OP的问题,但是没有人应该使用这种类型的标记进行引导分页。jsbin.com/eXaPibI/1
mg1075 2014年

1
实际上,我只是再次查看了第一个答案,并且生成的标记完全适合OP的用例,即使它不满足我的要求。OP希望li生成一个除法器项目,这是li您在jsbin中看到的额外项目。
Asad Saeeduddin 2014年

6

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

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

这样一个简单的指令实际上并不需要属性值,但可能会给您带来很多可能性,例如根据索引,长度等条件或完全不同的条件有条件地添加分隔符。


2
我添加了一个自定义指令,它很有效。该视频指南对您有所帮助:youtube.com/watch?
v=A6wq16Ow5Ec

3

我最近遇到了一个同样的问题,我不得不重复任意收集跨度和图像-不能在其周围添加元素-有一个简单的解决方案,但是创建一个“空”指令:

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元素,但是再次检查仍然没有...虽然仍然解决了我的布局问题...好奇心和好奇心...


replace从2.0开始不推荐使用。
demalexx 2014年

我尝试了上述操作,但是模板:“”导致未进行任何更改。我使用了jsfiddle.net/markcoleman/fMP9s/1中的链接器,并对其进行了修改:link:function(scope,element,attrs){element [0] .outerHTML =''; $ compile(element.contents())(作用域); }
Lauri Lubi 2015年

1

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

我想我看到一个有角力的团队说他们会在评论ng-repeats上工作,但是我不确定。您应该在存储库上为其打开一个问题。 http://github.com/angular/angular.js


来自2012年的评论。情况是否仍然如此?试图搜索他们的文档,但找不到任何参考。
Zack S

1

如果您使用的是Bootstrap,则没有Angular魔术方法可以执行此操作,对于您的情况,可以这样做以获得有效的HTML。然后,您将获得与添加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>

1

一个真正有效的解决方案

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指令将<remove>start和finish元素放置在<!--removed element-->


这是有趣的。但是,在我的测试replaceWith(...)结果中,文本节点不是注释。我发现只是使用element.remove()作品。
artfulrobot
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.