Iterate over an object for Handlebars?

37,390

Solution 1

Your current data format presents you with two problems:

  1. Handlebars really wants to iterate over arrays, not objects.
  2. JavaScript objects have no reliable order.

You'll have better luck if you can rearrange your data to be nested arrays, something like this:

var foods  = { /* what you already have */ };
var for_hb = [
        { name: 'Fruit',      foods: foods.Fruit },
        { name: 'Vegetables', foods: foods.Vegetables },
        //...
];

You can do that with something simple like this:

var for_hb = [ ];
for(var k in foods)
    for_hb.push({name: k, foods: foods[k]});
for_hb.sort(function(a, b) {
    a = a.name.toLowerCase();
    b = b.name.toLowerCase();
    return a < b ? -1
         : a > b ? +1
         :          0;
});

var html = compiled_template({ groups: for_hb });

Then your template is simple:

<select>
  <option value="">All Shows (default)</option>
  {{#each group}}
    <optgroup label="{{name}}">
    {{#each foods}}
      <option value="{{id}}">{{name}}</option>
    {{/each}}
  {{/each}}
</select>

You could write a helper to iterate over an object but you'd still have to specify the keys in an array if you wanted to be sure of a sensible display order.

Solution 2

use just "this"

`<script id="some-template" type="text/x-handlebars-template">
<option value="none">Selec</option>
{{#each data}}
    <optgroup label="{{@key}}">
    {{#each this}}
        <option value="{{id}}">{{name}}</option>
    {{/each}}
    </optgroup>
{{/each}}
</script>`

http://jsfiddle.net/rcondori/jfav4o6u/

Solution 3

You can do this via a custom component see example, this is not supported by our default {{each}} helper (and that is intentional).

Sample Data:

a = {a:'muhammad', b :'asif', c: 'javed', username: 'maxifjaved'}

**

Online Demo for iterate throw an Object

http://emberjs.jsbin.com/yuheke/1/edit?html,js,output

**

Share:
37,390
Rey
Author by

Rey

(your about me is currently blank)

Updated on July 09, 2022

Comments

  • Rey
    Rey almost 2 years

    So this is the general gist of my data (copied the look from chrome webkit inspector).

    > Object
      > Fruit: Array[2]
        > 0: Object
           name: "banana"
           color: "yellow"
           animalthateats: "monkey"
           id: 39480
        > 1: Object
        length: 2
      > Vegetables: Array[179]
      > Dairy: Array[2]
      > Meat: Array[3]
      > __proto__: Object
    

    And this is what I want to do (in general):

    <select>
      <option value="">All Shows (default)</option>
      <optgroup label="Fruit">
        <option value="39480">Banana</option>
        <option value="43432">Strawberry</option>
      </optgroup>
      <optgroup label="Vegetables">
        <option value="3432">Broccoli</option>
      </optgroup>
    </select>
    

    I'm sorta new to the whole templating thing, and it definitely seems non-straightforward to accomplish... if I can use jQuery anyway that will work too, but preferably just with this setup.