2012-05-01 97 views
45

我有一個Handlebars模板,我試圖從數組中生成逗號分隔的項目列表。除了最後一個元素之外,如何在{{#each}}循環中的元素之間添加分隔符?

在我把手模板:

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

我想,不上的最後一項顯示出來。有沒有辦法在Handlebars中做到這一點,或者我需要回退到CSS選擇器?

UPDATE:基於克里斯托弗的建議,這是我最終實現:

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

我發現另一件事是,如果你刪除最後一項,你需要強制重繪每個項目以刪除最後一個分隔符。默認情況下刪除一個項目似乎只刪除該項目的視圖,其他人沒有更新(這是有道理的)。 –

回答

48

您可以使用標準的CSS來做到這一點:

li:after { 
    content: ','; 
} 

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

我更喜歡單獨的規則,但如果稍微少一個更簡潔(來自@Jay的評論):

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

我看着最後一個孩子,雖然它會工作得很好,除非它在IE8中不受支持。我會給計算中的屬性一個鏡頭。對我來說,仍然有點奇怪,沒有內置的方式來創建分隔列表。 –

+5

而不是使用':after'和'last-child',你可以使用'li + li:before',這使得這個堅實的IE8證明(不要忘記[把它放在符合標準的渲染模式](http: //zurb.com/article/284/ie8-rendering-modes-one-meta-tag-to-rule-)!) –

+0

這是完美的!我正在使用Mustache.js模板,但直到我開始尋找替代品(我現在不需要!)時,我才發現它。 –

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('[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: "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}} 
+0

不幸的是,這不符合Ember.js中的數據綁定。 –

+0

您是否嘗試過計算屬性? – hellslam

+0

我最終做了類似這樣的事情,但使用了支持每個項目的Handlebars模板的Ember.js ContainerView,然後使用計算屬性來說明當前項目是否是父項目列表中的最後一個項目。看到我更新的答案。這看起來像一個不錯的選擇,如果你不需要使用花哨的HTML模板(就像我在做什麼)。 –

5

我意識到這是一個歲,但我有一個類似的概率lem並在這裏結束。就我而言,我實際上正在處理一個數組。所以,這是我的解決方案。

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

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

我正在尋找一種簡單而優雅的解決方案,它可以在模板中保留csv邏輯。

55

自Ember v1.11以來,您可以獲取每個使用塊參數的索引。在你的情況,這將是這個樣子:

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

第一index值將0這將評估爲false,不會被添加,所有的後續值將評估爲true將前面加上一個分隔符。

+0

這不符合問題。你仍然在最後一個元素中得到一個逗號... – mk2

+1

@MarcusRenno因此它在元素內容之前。 –

+0

是的,我不知道我在想什麼。現在即時通訊讀取代碼,這是完全有意義的 – mk2

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

我創建九月塊幫手:

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

用法:

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

支持else語句。

90

我知道我遲到了部分,但我發現了一個WAYYYY簡單的方法

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

這是一個 – redben

+14

這不是一個,如果你使用Ember的把手。 – 2014-12-30 16:24:54

+2

我沒有使用Ember,但是在尋找一種方法來完成這項工作時,我遇到了這個線程。謝謝! –

4

與Ember 2.7,你可以完成此操作後安裝ember-truth-helpers

ember install ember-truth-helpers 

,然後你的模板看起來像這樣:

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