【问题标题】: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}}

【问题讨论】:

  • 我发现的另一件事是,如果您删除最后一个项目,则需要强制重绘每个项目以删除最后一个分隔符。默认情况下,删除一个项目似乎只会删除该项目的视图,而其他项目不会更新(这是有道理的)。

标签: javascript ember.js handlebars.js


【解决方案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,而不是使用:afterlast-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}} stackoverflow.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 list}}{{this}}{{/csv}}
        

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

        【讨论】:

          【解决方案8】:

          也许在这种情况下,您应该为集合创建一个视图,而不是成员项上的视图迭代。在这种情况下,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}}
          

          【讨论】:

          • 不幸的是,这不适用于 Ember.js 中的数据绑定。
          • 我最终做了类似的事情,但使用了 Ember.js ContainerView,它支持每个项目的 Handlebars 模板,然后是一个计算属性,说明当前项目是否是父列表中的最后一个项目或不。请参阅我的更新答案。如果您不需要使用花哨的 HTML 模板(就像我正在做的那样),这看起来是一个不错的选择。
          猜你喜欢
          • 1970-01-01
          • 2018-06-01
          • 1970-01-01
          • 1970-01-01
          • 2011-01-15
          • 1970-01-01
          • 2019-11-04
          • 1970-01-01
          相关资源
          最近更新 更多