可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
As the title of question says, is there a mustache/handlebars way of looping through an object properties?
So with
var o = {
bob : \'For sure\',
roger: \'Unknown\',
donkey: \'What an ass\'
}
Can I then do something in the template engine that would be equivalent to
for(var prop in o)
{
// with say, prop a variable in the template and value the property value
}
?
回答1:
Built-in support since Handlebars 1.0rc1
Support for this functionality has been added to Handlebars.js, so there is no more need for external helpers.
How to use it
For arrays:
{{#each myArray}}
Index: {{@index}} Value = {{this}}
{{/each}}
For objects:
{{#each myObject}}
Key: {{@key}} Value = {{this}}
{{/each}}
Note that only properties passing the hasOwnProperty
test will be enumerated.
回答2:
It\'s actually quite easy to implement as a helper:
Handlebars.registerHelper(\'eachProperty\', function(context, options) {
var ret = \"\";
for(var prop in context)
{
ret = ret + options.fn({property:prop,value:context[prop]});
}
return ret;
});
Then using it like so:
{{#eachProperty object}}
{{property}}: {{value}}<br/>
{{/eachProperty }}
回答3:
EDIT: Handlebars now has a built-in way of accomplishing this; see the selected answer above.
When working with plain Mustache, the below still applies.
Mustache can iterate over items in an array. So I\'d suggest creating a separate data object formatted in a way Mustache can work with:
var o = {
bob : \'For sure\',
roger: \'Unknown\',
donkey: \'What an ass\'
},
mustacheFormattedData = { \'people\' : [] };
for (var prop in o){
if (o.hasOwnProperty(prop)){
mustacheFormattedData[\'people\'].push({
\'key\' : prop,
\'value\' : o[prop]
});
}
}
Now, your Mustache template would be something like:
{{#people}}
{{key}} : {{value}}
{{/people}}
Check out the \"Non-Empty Lists\" section here: https://github.com/janl/mustache.js
回答4:
This is @Ben\'s answer updated for use with Ember...note you have to use Ember.get
because context is passed in as a String.
Ember.Handlebars.registerHelper(\'eachProperty\', function(context, options) {
var ret = \"\";
var newContext = Ember.get(this, context);
for(var prop in newContext)
{
if (newContext.hasOwnProperty(prop)) {
ret = ret + options.fn({property:prop,value:newContext[prop]});
}
}
return ret;
});
Template:
{{#eachProperty object}}
{{key}}: {{value}}<br/>
{{/eachProperty }}
回答5:
@Amit\'s answer is good because it will work in both Mustache and Handlebars.
As far as Handlebars-only solutions, I\'ve seen a few and I like the each_with_key
block helper at https://gist.github.com/1371586 the best.
- It allows you to iterate over object literals without having to restructure them first, and
- It gives you control over what you call the key variable. With many other solutions you have to be careful about using object keys named
\'key\'
, or \'property\'
, etc.
回答6:
Thanks for Ben\'s solution, my use case to display only particular fields in order
with object
Code:
handlebars.registerHelper(\'eachToDisplayProperty\', function(context, toDisplays, options) {
var ret = \"\";
var toDisplayKeyList = toDisplays.split(\",\");
for(var i = 0; i < toDisplayKeyList.length; i++) {
toDisplayKey = toDisplayKeyList[i];
if(context[toDisplayKey]) {
ret = ret + options.fn({
property : toDisplayKey,
value : context[toDisplayKey]
});
}
}
return ret;
});
Source object:
{ locationDesc:\"abc\", name:\"ghi\", description:\"def\", four:\"you wont see this\"}
Template:
{{#eachToDisplayProperty this \"locationDesc,description,name\"}}
<div>
{{property}} --- {{value}}
</div>
{{/eachToDisplayProperty}}
Output:
locationDesc --- abc
description --- def
name --- ghi
回答7:
This is a helper function for mustacheJS, without pre-formatting the data and instead getting it during render.
var data = {
valueFromMap: function() {
return function(text, render) {
// \"this\" will be an object with map key property
// text will be color that we have between the mustache-tags
// in the template
// render is the function that mustache gives us
// still need to loop since we have no idea what the key is
// but there will only be one
for ( var key in this) {
if (this.hasOwnProperty(key)) {
return render(this[key][text]);
}
}
};
},
list: {
blueHorse: {
color: \'blue\'
},
redHorse: {
color: \'red\'
}
}
};
Template:
{{#list}}
{{#.}}<span>color: {{#valueFromMap}}color{{/valueFromMap}}</span> <br/>{{/.}}
{{/list}}
Outputs:
color: blue
color: red
(order might be random - it\'s a map)
This might be useful if you know the map element that you want. Just watch out for falsy values.
回答8:
I was using old version 1.0.beta.6
of handlebars, i think somewhere during 1.1 - 1.3 this functionality was added, so updating to 1.3.0 solved the issue, here is the usage:
Usage:
{{#each object}}
Key {{@key}} : Value {{this}}
{{/people}}