14

Say I have JSON:

{
userinput: [
    {name: "brian", "value": "i like pies"},
    {name: "susan", "value": "memes are stupid"}
],
feedback: [
    {value: "i also like pies"},
    {value: "null"}
]
}

And I'm trying to draw a table like this:

name ..... | input ......   | feedback
-----------|----------------|-----------------
brian      | I like pies    | I also like pies
susan      | mems are stupid| null

And while I recognise that it would be better to have feedback as a value of "userinput", what I have is not done like that ...

I'm trying to get the index of feedback inside {{#each userinput}}`, e.g.

{{#each userinput}}
<td>{{name}}</td><td>{{value}}</td><td>{{../feedback[@index].value}}</td>
{{/each}}

But of course {{../feedback[@index].value}} does not work.

What is the best way (without changing the structure of the json) to grab the value of the matching index inside the feedback array?

Rubens Mariuzzo
  • 28,358
  • 27
  • 121
  • 148
frumbert
  • 2,323
  • 5
  • 30
  • 61
  • Hey frumbert, I noticed you haven't selected an answer. Just wanted to point out that, while @Rubens Mariuzzo didn't work for me, [nickgraef 's answer](http://stackoverflow.com/a/32640060/923817) did. – D.Tate Nov 24 '15 at 18:59
  • 1
    @D.Tate at the time I was unable to upgrade handlebars since it used some javascript techniques that were too new for the javascript server side engine I was using; the version I had then didn't contain a lookup helper/method and did something like http://stackoverflow.com/a/18169209/1238884. – frumbert Nov 25 '15 at 03:59

2 Answers2

15

This can be accomplished using the lookup helper:

The lookup helper allows for dynamic parameter resolution using Handlebars variables. This is useful for resolving values for array indexes.

So the template for your example would look like this:

{{#each userinput}}
    <td>{{name}}</td>
    <td>{{value}}</td>
    <td>
        {{#with (lookup ../feedback @index)}}
            {{value}}
        {{/with}}
    </td>
{{/each}}
nickgraef
  • 2,397
  • 2
  • 22
  • 26
3

I guess you will have to write a block helper for this, as it seems @index can only be used as a stand-alone.

I modified the "list" example, to allow a template like this: "{{#list userinput feedback}}<td>{{name}}</td><td>{{value}}</td><td>{{@feedback.value}}</td>{{/list}}". The implementation is like this, accepting two parameters "input" and "feedback" (plus the standard "options").

Handlebars.registerHelper('list', function(input, feedback, options) {
  var out = "", data;

  // iterate over the input
  for (var i=0; i<input.length; i++) {
    if (options.data) {
      data = Handlebars.createFrame(options.data || {});

      // add "feedback" item to the current frame's data
      data.feedback = feedback[i];
    }

    out += "<tr>" + options.fn(input[i], { data: data }) + "</tr>";
  }

  return out;
});

Here's the Fiddle.

McGarnagle
  • 101,349
  • 31
  • 229
  • 260