66

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

在我的车把模板中:

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

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

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

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

8 回答 8

154

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

{{#unless @last}},{{/unless}}
于 2014-11-13T00:04:46.397 回答
60

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

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

第一个index值将被0评估为false不会被添加,所有后续值将评估为true将在分隔符前添加的值。

于 2013-10-03T09:12:49.223 回答
50

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

li:after {
    content: ',';
}

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

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

li:not(:last-of-type):after {
    content: ',';
}
于 2012-05-01T22:32:19.123 回答
6

我创建了 sep 块助手:

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

用法:

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

支持 else 语句。

于 2014-06-25T12:49:52.753 回答
5

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

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

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

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

于 2013-09-16T15:34:51.383 回答
4

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

ember install ember-truth-helpers

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

{{#each model as |e|}}
    {{e}}{{#unless (eq e model.lastObject)}}, {{/unless}}
{{/each}}
于 2016-10-16T16:28:51.447 回答
3

我得到了这个与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}}
于 2014-06-23T15:02:12.117 回答
2

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

模板:

{{App.listController.csv}}

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('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}}
于 2012-05-01T19:50:19.123 回答