Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get an array value at index using Handlebars.js?

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?

like image 759
frumbert Avatar asked Aug 11 '13 05:08

frumbert


2 Answers

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}}
like image 67
nickgraef Avatar answered Dec 18 '22 23:12

nickgraef


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.

like image 41
McGarnagle Avatar answered Dec 18 '22 23:12

McGarnagle