简体   繁体   English

AngularJS ng-repeat没有html元素

[英]AngularJS ng-repeat with no html element

I am currently using this piece of code to render a list: 我目前正在使用这段代码来呈现一个列表:

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

However, the <div> element is causing some very minor rendering defects on some browsers. 但是, <div>元素在某些浏览器上导致一些非常小的渲染缺陷。 I would like to know is there a way to do the ng-repeat without the div container, or some alternative method to achieve the same effect. 我想知道有没有办法在没有div容器的情况下进行ng-repeat,或者有一些替​​代方法来实现相同的效果。

As Andy Joslin said they were working on comment based ng-repeats but apparently there were too many browser issues . 正如安迪·乔斯林所说他们正在研究基于注释的ng-repeats, 但显然有太多的浏览器问题 Fortunately AngularJS 1.2 adds built-in support for repeating without adding child elements with the new directives ng-repeat-start and ng-repeat-end . 幸运的是,AngularJS 1.2增加了内置的重复支持,无需使用新指令ng-repeat-startng-repeat-end添加子元素。

Here's a little example for adding Bootstrap pagination : 这是添加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>

A full working example can be found here . 这里可以找到完整的工作示例。

John Lindquist also has a video tutorial of this over at his excellent egghead.io page . John Lindquist还在他出色的egghead.io页面上有一个关于此视频教程

KnockoutJS containerless binding syntax KnockoutJS无容器绑定语法

Please bear with me a second: KnockoutJS offers an ultra-convenient option of using a containerless binding syntax for its foreach binding as discussed in Note 4 of the foreach binding documentation. 请耐心等一下:KnockoutJS为foreach绑定提供了一个使用无容器绑定语法的超便捷选项,如foreach绑定文档的注释4中所述。 http://knockoutjs.com/documentation/foreach-binding.html http://knockoutjs.com/documentation/foreach-binding.html

As the Knockout documentation example illustrates, you can write your binding in KnockoutJS like this: 正如Knockout文档示例所示,您可以在KnockoutJS中编写绑定,如下所示:

<ul>
    <li class="header">Header item</li>
    <!-- ko foreach: myItems -->
        <li>Item <span data-bind="text: $data"></span></li>
    <!-- /ko -->
</ul>

I think it is rather unfortunate AngularJS does not offer this type of syntax. 我认为这是相当不幸的AngularJS不提供这种语法。


Angular's ng-repeat-start and ng-repeat-end Angular的ng-repeat-startng-repeat-end

In the AngularJS way to solve ng-repeat problems, the samples I come across are of the type jmagnusson posted in his (helpful) answer. 在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>

My original thought upon seeing this syntax is: really? 看到这种语法后,我原来的想法是:真的吗? Why is Angular forcing all this extra markup that I want nothing to do with and that is so much easier in Knockout? 为什么Angular强制所有这些额外的标记,我想要什么都没有,这在Knockout中更容易? But then hitautodestruct's comment in jmagnusson's answer started making me wonder: what is being generated with ng-repeat-start and ng-repeat-end on separate tags? 但是hitautodestruct在jmagnusson的回答中的评论开始让我想知道:在单独的标签上使用ng-repeat-start和ng-repeat-end生成什么?


A cleaner way to use ng-repeat-start and ng-repeat-end 使用ng-repeat-startng-repeat-end更简洁方法

Upon investigation of hitautodestruct's assertion, adding ng-repeat-end on to a separate tag is exactly what I would not want to do in most cases, because it generates utterly usesless elements: in this case, <li> items with nothing in them. 在hitautodestruct的说法进行调查,将ng-repeat-end上一个单独的标签是什么我希望在大多数情况下这样做,因为它会产生完全usesless元素:在这种情况下, <li>有没有在他们的项目。 Bootstrap 3's paginated list styles the list items so that it looks like you did not generate any superfluous items, but when you inspect the generated html, they are there. Bootstrap 3的分页列表对列表项进行样式设置,使得它看起来不会生成任何多余的项,但是当您检查生成的html时,它们就在那里。

Fortunately , you do not need to do much to have a cleaner solution and a shorter amount of html: just put the ng-repeat-end declaration on the same html tag that has the ng-repeat-start . 幸运的是 ,你不需要做太多的事情来获得更清晰的解决方案和更少量的html: 只需将ng-repeat-end声明放在具有ng-repeat-start的相同html标签上

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

This gives 3 advantages: 这有三个好处:

  1. less html tags to write 写的html标签少
  2. useless, empty tags are not generated by Angular Angular不会生成无用的空标签
  3. when the array to repeat is empty, the tag with ng-repeat won't get generated, giving you the same advantage Knockout's containerless binding gives you in this regard 当要重复的数组为空时,不会生成带有ng-repeat的标记,为您提供相同的优势Knockout的无容器绑定在这方面为您提供

But there is still a cleaner way 但仍有一种更清洁的方式

After further reviewing the comments in github on this issue for Angular, https://github.com/angular/angular.js/issues/1891 , 在进一步审查github关于Angular这个问题的评论之后, https://github.com/angular/angular.js/issues/1891
you do not need to use ng-repeat-start and ng-repeat-end to achieve the same advantages. 您不需要使用ng-repeat-startng-repeat-end来实现相同的优势。 Instead, forking again jmagnusson's example, we can just go: 相反,再次分享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>

So when to use ng-repeat-start and ng-repeat-end ? 那么何时使用ng-repeat-startng-repeat-end As per the angular documentation , to 根据角度文档 ,到

...repeat a series of elements instead of just one parent element... ...重复一系列元素而不只是一个父元素......

Enough talk, show some examples! 足够的谈话,展示一些例子!

Fair enough; 很公平; this jsbin walks through five examples of what happens when you do and when you don't use ng-repeat-end on the same tag. 这个jsbin通过五个例子来说明当你这样做时以及你在同一个标​​签上不使用ng-repeat-end时会发生什么。

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

ngRepeat may not be enough, however you can combine that with a custom directive. ngRepeat可能还不够,但您可以将它与自定义指令结合使用。 You could delegate the the task of adding divider items to code if you don't mind a little bit of jQuery. 如果你不介意一点点jQuery,你可以委托将divider项添加到代码中的任务。

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

Such a simple directive doesn't really need an attribute value but might give you lots of possiblities like conditionally adding a divider according to index, length, etc or something completely different. 这样一个简单的指令并不需要一个属性值,但可能会给你很多可能性,比如根据索引,长度等有条件地添加一个分隔符或者完全不同的东西。

I recently had the same problem in that I had to repeat an arbitrary collection of spans and images - having an element around them was not an option - there's a simple solution however, create a "null" directive: 我最近遇到了同样的问题,因为我必须重复一个任意的跨度和图像集合 - 周围有一个元素不是一个选项 - 但是,有一个简单的解决方案,创建一个“null”指令:

app.directive("diNull", function() {
        return {
            restrict: "E",
            replace: true,
            template: ""
        };
    });

You can then use a repeat on that Element, where element.url points to the template for that element: 然后,您可以在该Element上使用repeat,其中element.url指向该元素的模板:

<di-null ng-repeat="element in elements" ng-include="element.url" ></di-null>

This will repeat any number of different templates with no container around them 这将重复任意数量的不同模板,周围没有容器

Note: hmm I could've sworn blind this removed the di-null element when rendering, but checking it again it doesn't...still solved my layout issues though...curioser and curioser... 注意:嗯,我可以发誓盲目在渲染时删除了di-null元素,但再次检查它不会......仍然解决了我的布局问题,但是...好奇者和好奇者......

There is a comment directive restriction, but ngRepeat doesn't support it (since it needs an element to repeat). 有一个注释指令限制,但ngRepeat不支持它(因为它需要一个元素重复)。

I think I saw the angular team say they would work on comment ng-repeats, but I'm not sure. 我想我看到有角度的团队说他们会继续评论重复评论,但我不确定。 You should open an issue for it on the repo. 您应该在回购中为它打开一个问题。 http://github.com/angular/angular.js http://github.com/angular/angular.js

There is no Angular magic way to do this, for your case you can do this, to get valid HTML, if you are using Bootstrap. 没有Angular魔术方法可以做到这一点,对于你的情况你可以这样做,以获得有效的HTML,如果你使用Bootstrap。 Then you will get same effect as adding the li.divider 然后你将获得与添加li.divider相同的效果

Create a class: 创建一个类:

span.divider {
 display: block;
}

Now change your code to this: 现在将代码更改为:

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

for a solution that really works 一个真正有效的解决方案

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

add an angular.js directive 添加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]);
}());

for a brief explanation, 为了简要说明,

ng-repeat binds itself to the <remove> element and loops as it should, and because we have used ng-repeat-start / ng-repeat-end it loops a block of html not just an element. ng-repeat将自身绑定到<remove>元素并按原样循环,因为我们使用了ng-repeat-start / ng-repeat-end,它循环一个html块而不仅仅是一个元素。

then the custom remove directive places the <remove> start and finish elements with <!--removed element--> 然后自定义remove指令将<remove>开始和结束元素放在<!--removed element-->

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM