除了最后一个元素之后,如何在 #each 循环中的元素之间添加分隔符?
Posted
技术标签:
【中文标题】除了最后一个元素之后,如何在 #each 循环中的元素之间添加分隔符?【英文标题】:How do I add a separator between elements in an #each loop except after the last element?除了最后一个元素之后,如何在 #each 循环中的元素之间添加分隔符? 【发布时间】:2012-05-11 07:02:03 【问题描述】:我有一个 Handlebars 模板,我正在尝试从数组中生成以逗号分隔的项目列表。
在我的 Handlebars 模板中:
#each list
name status,
/each
我希望,
不显示在最后一项上。有没有办法在 Handlebars 中做到这一点,还是我需要回退到 CSS 选择器?
更新:根据 Christopher 的建议,这是我最终实施的:
var attachments = Ember.CollectionView.extend(
content: [],
itemViewClass: Ember.View.extend(
templateName: 'attachments',
tagName: 'span',
isLastItem: function()
return this.getPath('parentView.content.lastObject') == this.get('content');
.property('parentView.content.lastObject').cacheable()
)
));
在我看来:
collection attachments
和项目视图:
content.title (content.size) #unless isLastItem, /unless
【问题讨论】:
我发现的另一件事是,如果您删除最后一个项目,则需要强制重绘每个项目以删除最后一个分隔符。默认情况下,删除一个项目似乎只会删除该项目的视图,而其他项目不会更新(这是有道理的)。 【参考方案1】:您可以使用标准 CSS 来执行此操作:
li:after
content: ',';
li:last-of-type:after
content: '';
我更喜欢单独的规则,但更简洁但可读性稍差的版本(来自 cmets 中的 @Jay):
li:not(:last-of-type):after
content: ',';
【讨论】:
我研究了 last-child ,虽然它会很好用,除了它在 IE8 中不受支持。我会给计算的属性一个镜头。没有内置的方式来制作分隔列表,这对我来说仍然很奇怪。 您可以使用li + li:before
,而不是使用:after
和last-child
,这使得它能够可靠地抵御IE8(不要忘记put it in standards compliant rendering mode!)
这太完美了!我将它与 Mustache.js 模板一起使用,但直到我开始四处寻找替代品(我现在不需要它!)时才找到它。
我已经编辑了下面的答案,也许您也应该将这种新语法合并到您的答案中。
我进行了编辑以删除旧的笨拙的后备。如果你还在关心 IE8……上帝怜悯你的灵魂。我仍然更喜欢明确的单独规则,但每个人都有自己的规则。【参考方案2】:
使用 ember 2.7,您可以在安装 ember-truth-helpers
后执行此操作:
ember install ember-truth-helpers
然后您的模板将如下所示:
#each model as |e|
e#unless (eq e model.lastObject), /unless
/each
【讨论】:
【参考方案3】:从 Ember v1.11 开始,您可以使用块参数获取每个索引的索引。在你的情况下,这看起来像这样:
#each list as |item index|
if index ", "item.name item.status
/each
第一个index
值将是0
,它将评估为false
并且不会被添加,所有后续值将评估为true
,它将在前面添加一个分隔符。
【讨论】:
这不符合问题。你仍然在最后一个元素中得到一个逗号...... @MarcusRenno 因此它位于元素内容之前。 是的,我不知道我在想什么。现在我再次阅读代码完全有意义【参考方案4】:我知道我迟到了,但我找到了一个 WAYYYY 更简单的方法
#unless @last,/unless
【讨论】:
如果您使用 Ember 的车把,这不是。 我没有使用 Ember,但我在寻找一种方法时遇到了这个线程,它运行良好。谢谢! 类似的注释:#if @index,/if
***.com/a/20575093/923745 -- 应该与 Ember 一起使用。
如果您想知道的话,可以在 jsreport 车把引擎中完美运行【参考方案5】:
我已经创建了 sep 块助手:
Handlebars.registerHelper("sep", function(options)
if(options.data.last)
return options.inverse();
else
return options.fn();
);
用法:
#each Data
Text#sep,/sep
/each
支持 else 语句。
【讨论】:
【参考方案6】:我得到了这个修改版本的freak3dot的答案:
handlebars.registerHelper('csv', function(items, options)
return items.map(function(item)
return options.fn(item)
).join(', ')
)
(这是一个节点应用程序,因此如果您在浏览器中构建,请将map
相应地更改为下划线或其他内容)
允许在每个逗号之间格式化对象:
#csv players
firstName lastName
/csv
编辑:这是一个更灵活的版本。在任意分隔符上加入事物列表。
handlebars.registerHelper('join', function(items, separator, options)
return items.map(function(item)
return options.fn(item)
).join(separator)
)
和模板:
#join players ' vs '
firstName lastName
/join
【讨论】:
【参考方案7】:我意识到这已经一岁了,但我遇到了类似的问题并在这里结束了。就我而言,我实际上是在处理一个数组。所以,这是我的解决方案。
Handlebars.registerHelper('csv', function(items, options)
return options.fn(items.join(', '));
);
// then your template would be
#csv listthis/csv
我想要一个简单而优雅的解决方案,将 csv 逻辑保留在模板中。
【讨论】:
【参考方案8】:也许在这种情况下,您应该为集合创建一个视图,而不是成员项上的视图迭代。在这种情况下,Handlebar 迭代器是多余的。在下面的示例中,对 Person 对象的 firstName 或 lastName 的更改将绑定到列表并更新视图。
模板:
App.listController.csv
App = Ember.Application.create();
var Person = Ember.Object.extend(
firstName: null,
lastName: null
);
var bob = Person.create(
firstName: "bob",
lastName: "smith"
);
var ann = Person.create(
firstName: "ann",
lastName: "doe"
);
App.listController = Ember.Object.create(
list: [bob, ann],
csv: Ember.computed(function ()
var arr = [];
this.get('list').forEach(function (item, index, self)
arr.push(item.firstName + ' ' + item.lastName);
)
return arr.join(',');
).property('list.@each.firstName', 'list.@each.lastName')
);
// any changes to bob or ann will update the view
bob.set('firstName', 'tim');
// adding or removing from the array will update the view
App.listController.get('list').pushObject(Person.create(firstName: "Jack", lastName:"Dunn");
以下是我的原始答案,不适用于这种情况。
你应该可以通过助手来做到这一点:
Handlebars.registerHelper('csv', function(items, options)
var out = "";
for(var i=0, l=items.length; i<l; i++)
out += options.fn(items[i]);
if (i < l - 1)
out += ',';
// might want to add a newline char or something
return out;
);
// then your template would be
#csv list name status /each
【讨论】:
不幸的是,这不适用于 Ember.js 中的数据绑定。 我最终做了类似的事情,但使用了 Ember.js ContainerView,它支持每个项目的 Handlebars 模板,然后是一个计算属性,说明当前项目是否是父列表中的最后一个项目或不。请参阅我的更新答案。如果您不需要使用花哨的 html 模板(就像我正在做的那样),这看起来是一个不错的选择。以上是关于除了最后一个元素之后,如何在 #each 循环中的元素之间添加分隔符?的主要内容,如果未能解决你的问题,请参考以下文章
你如何找到 For Each (VB.NET) 中的最后一个循环?
如何在 $.each 中的 jquery prependTo 之前和之后添加静态 HTML