Javascript 除了最后一个元素之后,如何在 {{#each}} 循环中的元素之间添加分隔符?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10403003/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 01:10:20  来源:igfitidea点击:

How do I add a separator between elements in an {{#each}} loop except after the last element?

javascriptember.jshandlebars.js

提问by Chris Thompson

I have a Handlebars template where I'm trying to generate a comma-separated list of items from an array.

我有一个 Handlebars 模板,我试图从一个数组中生成一个逗号分隔的项目列表。

In my Handlebars template:

在我的把手模板中:

{{#each list}}
    {{name}} {{status}},
{{/each}}

I want the ,to not show up on the last item. Is there a way to do this in Handlebars or do I need to fall back to CSS selectors?

我希望,不要出现在最后一个项目上。有没有办法在 Handlebars 中做到这一点,还是我需要回退到 CSS 选择器?

UPDATE: Based on Christopher's suggestion, this is what I ended up implementing:

更新:根据克里斯托弗的建议,这就是我最终实施的:

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()
    })
}));

and in my view:

在我看来:

{{collection attachments}}

and the item view:

和项目视图:

{{content.title}} ({{content.size}}) {{#unless isLastItem}}, {{/unless}}

采纳答案by Christopher Swasey

You can use standard CSS to do this:

您可以使用标准 CSS 来执行此操作:

li:after {
    content: ',';
}

li:last-of-type:after {
    content: '';
}

I prefer separate rules, but a more concise if slightly less readable version (from @Jay in the comments):

我更喜欢单独的规则,但更简洁但可读性稍差的版本(来自评论中的@Jay):

li:not(:last-of-type):after {
    content: ',';
}

回答by MylesBorins

I know I'm late to the parts but I found a WAYYYY simpler method

我知道我迟到了,但我找到了一个更简单的方法

{{#unless @last}},{{/unless}}

回答by Nahkala

Since Ember v1.11 you are able to get the index of an each using block parameters. In your case this would look something like this:

从 Ember v1.11 开始,您可以使用块参数获取 each 的索引。在您的情况下,这看起来像这样:

{{#each list as |item index|}}
    {{if index ", "}}{{item.name}} {{item.status}}
{{/each}}

The first indexvalue will be 0which will evaluate to falseand will not be added, all subsequent values will evaluate to truewhich will prepend a separator.

第一个index值将是0which 将评估为false并且不会被添加,所有后续值将评估为truewhich 将在前面添加一个分隔符。

回答by freak3dot

I realize this is a year old but I had a similar problem and wound up here. In my case, I was actually dealing with an array. So, here's my solution.

我意识到这是一岁了,但我遇到了类似的问题并在这里结束。就我而言,我实际上是在处理一个数组。所以,这是我的解决方案。

Handlebars.registerHelper('csv', function(items, options) {
    return options.fn(items.join(', '));
});

// then your template would be
{{#csv list}}{{this}}{{/csv}}

I was going for a simple and elegant solution that keeps the csv logic in the template.

我想要一个简单而优雅的解决方案,将 csv 逻辑保留在模板中。

回答by albertjan

With ember 2.7 you can do this after you install ember-truth-helpers:

使用 ember 2.7,您可以在安装后执行此操作ember-truth-helpers

ember install ember-truth-helpers

and then your template will look like this:

然后您的模板将如下所示:

{{#each model as |e|}}
    {{e}}{{#unless (eq e model.lastObject)}}, {{/unless}}
{{/each}}

回答by Jadro007

I have created sep block helper:

我创建了 sep 块助手:

Handlebars.registerHelper("sep", function(options){
    if(options.data.last) {
        return options.inverse();
    } else {
        return options.fn();
    }
});

Usage:

用法:

{{#each Data}}
   {{Text}}{{#sep}},{{/sep}}
{{/each}}

Supports else statement.

支持 else 语句。

回答by mmacaulay

I got this working with a modified version of freak3dot's answer:

我使用 freak3dot 答案的修改版本得到了这个:

handlebars.registerHelper('csv', function(items, options) {
  return items.map(function(item) {
    return options.fn(item)
  }).join(', ')
})

(This is a node app, so change the mapaccordingly to underscore or whatever if you're building in the browser)

(这是一个节点应用程序,因此map如果您在浏览器中构建,请相应地将其更改为下划线或其他任何内容)

Allows for formatting objects between each comma:

允许在每个逗号之间格式化对象:

{{#csv players}
  {{firstName}} {{lastName}}
{{/csv}}

Edit: Here's a more flexible version. Join a list of things on an arbitrary separator.

编辑:这是一个更灵活的版本。在任意分隔符上加入事物列表。

handlebars.registerHelper('join', function(items, separator, options) {
  return items.map(function(item) {
    return options.fn(item)
  }).join(separator)
})

And template:

和模板:

{{#join players ' vs '}
  {{firstName}} {{lastName}}
{{/join}}

回答by hellslam

Maybe for this context, you should be creating a view for the collection, not an iteration of views on the member items. In this case, a Handlebar iterator is overkill. In my example below, changes to the firstName or lastName on the Person objects will be bound to the list and update the view.

也许对于这种情况,您应该为集合创建视图,而不是对成员项的视图迭代。在这种情况下,一个 Handlebar 迭代器是矫枉过正的。在下面的示例中,对 Person 对象的 firstName 或 lastName 的更改将绑定到列表并更新视图。

Template:

模板:

{{App.listController.csv}}

Javascript:

Javascript:

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('[email protected]', '[email protected]')
});
// 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: "Hyman", lastName:"Dunn"});

Below is my original answer, that didn't work for this context.

以下是我的原始答案,不适用于此上下文。

You should be able to do this with a helper:

您应该可以使用助手来做到这一点:

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