Handlebars/Mustache - Is there a built in way to loop through the properties of an object?

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
}

?

Answers:

Answer

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.

Answer

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

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

Answer

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

@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.
Answer

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
Answer

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.

Answer

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

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.