![](/img/trans.png)
[英]Ember.js / Ember-i18n: Is it possible to iterate over properties within a translation file from within a Handlebars template?
[英]How can I make Ember.js handlebars #each iterate over objects?
我正在嘗試使{{#each}}
助手遍歷一個對象,就像在香草把手中一樣。 不幸的是,如果我在一個對象上使用 #each,Ember.js 版本會給我這個錯誤:
Assertion failed: The value that #each loops over must be an Array. You passed [object Object]
我寫了這個助手來試圖解決這個問題:
Ember.Handlebars.helper('every', function (context, options) {
var oArray = [];
for (var k in context) {
oArray.push({
key : k,
value : context[k]
})
}
return Ember.Handlebars.helpers.each(oArray, options);
});
現在,當我嘗試使用{{#every}}
,出現以下錯誤:
Assertion failed: registerBoundHelper-generated helpers do not support use with Handlebars blocks.
這似乎是一個基本功能,我知道我可能遺漏了一些明顯的東西。 任何人都可以幫忙嗎?
編輯:
這是一個小提琴: http : //jsfiddle.net/CbV8X/
使用{{each-in}}
助手。 你可以像{{each}}
助手一樣使用它。
例子:
{{#each-in modelWhichIsObject as |key value|}}
`{{key}}`:`{{value}}`
{{/each-in}}
在擺弄了幾個小時之后,我想出了這個 hacky 方法:
Ember.Handlebars.registerHelper('every', function(context, options) {
var oArray = [], actualData = this.get(context);
for (var k in actualData) {
oArray.push({
key: k,
value: actualData[k]
})
}
this.set(context, oArray);
return Ember.Handlebars.helpers.each.apply(this,
Array.prototype.slice.call(arguments));
});
我不知道this.set
有什么影響,但這似乎有效!
這是一個小提琴: http : //jsfiddle.net/CbV8X/1/
我一直在追求類似的功能,因為我們正在分享我們的hacky方式,這是我不耐煩的小提琴: http : //jsfiddle.net/L6axcob8/1/
這個小提琴基於@lxe 提供的小提琴,由@Kingpin2k 更新,然后是我自己。
Ember:1.9.1,把手:2.0.0,jQuery 2.1.3
在這里,我們添加了一個名為every
的助手,它可以迭代對象和數組。
例如這個模型:
model: function() {
return {
properties: {
foo: 'bar',
zoo: 'zar'
}
};
}
可以使用以下把手模板進行迭代:
<ul class="properties">
{{#every p in properties}}
<li>{{p.key}} : {{p.value}}</li>
{{/every}}
</ul>
every
助手的工作方式是從對象鍵創建一個數組,然后通過 ArrayController 協調對 Ember 的更改。 是的,哈奇。 但是,如果該對象支持 [] 屬性的觀察,那么讓我們向/從對象添加/刪除屬性。
在我的用例中,我有一個 Ember.Object 派生類,它在添加/刪除屬性時通知 []。 我建議查看 Ember.Set 以獲得此功能,盡管我發現 Set 最近已被棄用。 由於這稍微超出了這個問題的范圍,我將其作為練習留給讀者。 這是一個提示:setUnknownProperty
為了收到屬性更改的通知,我們將非對象值包裝在我稱之為DataValueObserver 中,它設置(目前是一種方式)綁定。 這些綁定在我們內部 ArrayController 持有的值和我們正在觀察的對象之間提供了一座橋梁。
處理對象時; 我們將它們包裝在 ObjectProxy 中,這樣我們就可以引入一個“關鍵”成員,而無需修改對象本身。 為什么是的,這確實意味着您可以遞歸地使用 #every。 讀者的另一個練習;-)
我建議讓你的模型基於 Ember.Object 以與 Ember 的其余部分保持一致,允許你通過它的 get & set 處理程序來操縱你的模型。 或者,如小提琴中所示,您可以使用 Em.Get/Em.set 來訪問模型,只要您這樣做是一致的。 如果您直接觸摸您的模型(沒有獲取/設置),那么every
都不會收到您的更改通知。
Em.set(model.properties, 'foo', 'asdfsdf');
為了完整起見,這是我的every
幫手:
var DataValueObserver = Ember.Object.extend({
init: function() {
this._super();
// one way binding (for now)
Em.addObserver(this.parent, this.key, this, 'valueChanged');
},
value: function() {
return Em.get(this.parent, this.key);
}.property(),
valueChanged: function() {
this.notifyPropertyChange('value');
}
});
Handlebars.registerHelper("every", function() {
var args = [].slice.call(arguments);
var options = args.pop();
var context = (options.contexts && options.contexts[0]) || this;
Ember.assert("Must be in the form #every foo in bar ", 3 == args.length && args[1] === "in");
options.hash.keyword = args[0];
var property = args[2];
// if we're dealing with an array we can just forward onto the collection helper directly
var p = this.get(property);
if (Ember.Array.detect(p)) {
options.hash.dataSource = p;
return Ember.Handlebars.helpers.collection.call(this, Ember.Handlebars.EachView, options);
}
// create an array that we will manage with content
var array = Em.ArrayController.create();
options.hash.dataSource = array;
Ember.Handlebars.helpers.collection.call(this, Ember.Handlebars.EachView, options);
//
var update_array = function(result) {
if (!result) {
array.clear();
return;
}
// check for proxy object
var result = (result.isProxy && result.content) ? result.content : result;
var items = result;
var keys = Ember.keys(items).sort();
// iterate through sorted array, inserting & removing any mismatches
var i = 0;
for ( ; i < keys.length; ++i) {
var key = keys[i];
var value = items[key];
while (true) {
var old_obj = array.objectAt(i);
if (old_obj) {
Ember.assert("Assume that all objects in our array have a key", undefined !== old_obj.key);
var c = key.localeCompare(old_obj.key);
if (0 === c) break; // already exists
if (c < 0) {
array.removeAt(i); // remove as no longer exists
continue;
}
}
// insert
if (typeof value === 'object') {
// wrap object so we can give it a key
value = Ember.ObjectProxy.create({
content: value,
isProxy: true,
key: key
});
array.insertAt(i, value);
} else {
// wrap raw value so we can give it a key and observe when it changes
value = DataValueObserver.create({
parent: result,
key: key,
});
array.insertAt(i, value);
}
break;
}
}
// remove any trailing items
while (array.objectAt(i)) array.removeAt(i);
};
var should_display = function() {
return true;
};
// use bind helper to call update_array if the contents of property changes
var child_properties = ["[]"];
var preserve_context = true;
return Ember.Handlebars.bind.call(context, property, options, preserve_context, should_display, update_array, child_properties);
});
靈感來自:
如果你錯過了,這里又是那個小提琴:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.