Create a gist now

Instantly share code, notes, and snippets.

Handlebars.js helpers to iterate over objects
// HELPER: #key_value
//
// Usage: {{#key_value obj}} Key: {{key}} // Value: {{value}} {{/key_value}}
//
// Iterate over an object, setting 'key' and 'value' for each property in
// the object.
Handlebars.registerHelper("key_value", function(obj, fn) {
var buffer = "",
key;
for (key in obj) {
if (obj.hasOwnProperty(key)) {
buffer += fn({key: key, value: obj[key]});
}
}
return buffer;
});
// HELPER: #each_with_key
//
// Usage: {{#each_with_key container key="myKey"}}...{{/each_with_key}}
//
// Iterate over an object containing other objects. Each
// inner object will be used in turn, with an added key ("myKey")
// set to the value of the inner object's key in the container.
Handlebars.registerHelper("each_with_key", function(obj, fn) {
var context,
buffer = "",
key,
keyName = fn.hash.key;
for (key in obj) {
if (obj.hasOwnProperty(key)) {
context = obj[key];
if (keyName) {
context[keyName] = key;
}
buffer += fn(context);
}
}
return buffer;
});
@rclayton-the-terrible

This is a helper that really should be apart of the Handlebars core API.

@rclayton-the-terrible

This is a helper that really should be apart of the Handlebars core API.

@pdeschen
pdeschen commented Oct 4, 2012

I think that starting from 2.x release, callback should be function(obj, options) and instead of fn(), one should use options.fn()

@krisdahl

I made those changes in a fork and it is now working for me. I agree it should be included in handlebars core API.

@letitia
letitia commented Oct 25, 2012

Agree with pdeschen, the code in this gist is buggy and that's how I fixed it too.

@zhangming1978

Great helper! should be included in core.

Thanks strathmeyer

@kowal
kowal commented Apr 9, 2013

Coffeescript version of key_value which worked for me:

Handlebars.registerHelper 'key_value', (obj, hash) ->
  buffer = ""

  for key of obj
    if obj.hasOwnProperty(key)
      buffer += hash.fn({ key: key, value: obj[key] })

  buffer
@spicyj
spicyj commented Apr 23, 2013

@kowal You can simplify that code a bit:

Handlebars.registerHelper 'key_value', (obj, hash) ->
  buffer = ""

  for own key, value of obj
      buffer += hash.fn({ key, value })

  buffer
@athleticus

In the case of there being an empty string template between the key_value tag pair, this will output undefined for each property in the object being iterated. I think it is best practice to avoid this, and it can be done by defaulting to an empty string if the return of hash.fn({ key, value }) is falsey. See below:

CS

Handlebars.registerHelper 'key_value', (obj, hash) ->
  buffer = ""

  for own key, value of obj
      buffer += hash.fn({ key, value }) || ''

  buffer

JS

Handlebars.registerHelper('key_value', function (obj, hash) {
    var buffer, key, value;
    buffer = "";
    for (key in obj) {
        if (!Object.hasOwnProperty.call(obj, key)) {
            continue;
        }
        buffer += hash.fn({
            key: key,
            value: obj[key]
        }) || '';
    }
    return buffer;
});
@calidion

This is a helper that really should be apart of the Handlebars core API.

@alexnordstrom

@calidion it is, For object iteration, use {{@key}} instead:
{{#each object}}
{{@key}}: {{this}}
{{/each}}

@connor1995JS

Handlebars now supports looping objects, but as far as i know ember does not

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment