Handlebars JS get the subarray item using variable

982 Views Asked by At

I have json with an array of objects which each object has its own sub array.

I want to grab the values from _History sub array using the value in _Year variable I pass into Handlebars js. I can get it to work if I set the value directly into the code ex: {{_History.[2018].Testa}}.

Is it possible to set the value of _Year and have handlebars get the right sub array?

The parameter values I pass to handlebars js.

    var params = {
        _Person: "THE JSON",
        _Year: "2018"
    };

JSON Code:

        [
            {
            "_History": {
                "2017": {
                "Testa": "Test 1",
                "Testb": "Test 2"
                },
                "2018": {
                "Testa": "Test 3",
                "Testb": "Test 4"
                }
            },
            "FirstName": "John",
            "LastName": "Doe"
            },
            {
            "_History": {
                "2017": {
                "Testa": "Test 5",
                "Testb": "Test 6"
                },
                "2018": {
                "Testa": "Test 7",
                "Testb": "Test 8"
                }
            },
            "FirstName": "Susan",
            "LastName": "Doe"
            }
        ]

Handlebars JS template:

        {{#each _Person}}
        <tr>
            <td nowrap>{{FirstName}}</td>
            <td nowrap>{{LastName}}</td>
            <td nowrap>{{_History.[2018].Testa}}</td>      <-- Works
            <td nowrap>{{_History.[../_Year].Testa}}</td>  <-- Doesn't Work
            <td nowrap>{{_History.[../@_Year].Testa}}</td> <-- Doesn't Work
            <td nowrap>{{_History.[@../_Year].Testa}}</td> <-- Doesn't Work
        </tr>
        {{/each}}
1

There are 1 best solutions below

0
On BEST ANSWER

Since you want to perform a dynamic lookup you will need to use the lookup helper specifically built for that.

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

{{lookup _History ../_Year}} //Object

After the dynamic lookup you will need to perform another one to access 'Testa' or 'Testb'

You can use a subexpression for this:

<td nowrap>{{lookup (lookup _History ../_Year) 'Testa'}}</td>

If you don't like using subexpressions or need a much deeper lookup I made a custom helper that it's a little easier to use:

Handlebars.registerHelper('coolerLookup', function(){
   var args = [].slice.call(arguments);

   var block = args.pop();
   var object = args.shift();

   var value = args.reduce(function(a, b) {
      return a[b];
   }, object);

   return value;
});

Now you can do:

<td nowrap>{{coolerLookup _History ../_Year 'Testa'}}</td>
<td nowrap>{{coolerLookup _History ../_Year 'deep' 'deeper' 'property'}}</td>

Working demo:

var data = {
 "_Person": [{
  "_History": {
   "2017": {
    "Testa": "Test 1",
    "Testb": "Test 2"
   },
   "2018": {
    "Testa": "Test 3",
    "Testb": "Test 4"
   }
  },
  "FirstName": "John",
  "LastName": "Doe"
 }, {
  "_History": {
   "2017": {
    "Testa": "Test 5",
    "Testb": "Test 6"
   },
   "2018": {
    "Testa": "Test 7",
    "Testb": "Test 8"
   }
  },
  "FirstName": "Susan",
  "LastName": "Doe"
 }],
 "_Year": "2018"
};

Handlebars.registerHelper('coolerLookup', function(){
   var args = [].slice.call(arguments);
   
   var block = args.pop();
   var object = args.shift();
      
   var value = args.reduce(function(a, b) {
      return a[b];
   }, object);
   
   return value;
});

var source   = $("#template").html();
var template = Handlebars.compile(source);

$("#output").html(template(data));
td {
  width: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<script src="http://builds.handlebarsjs.com.s3.amazonaws.com/handlebars-v4.0.5.js"></script>

<script id="template" type="text/x-handlebars-template">
  {{#each _Person}}
        <tr>
            <td nowrap>{{FirstName}}</td>
            <td nowrap>{{LastName}}</td>
            <td nowrap>{{lookup (lookup _History ../_Year) 'Testa'}}</td>  <-- It Works now-->
            <td nowrap>{{lookup (lookup _History ../_Year) 'Testb'}}</td>  <-- It Works now-->
            <td nowrap>{{coolerLookup _History ../_Year 'Testa'}}</td> <!-- deal with it -->
        </tr>
  {{/each}}
</script>

<div id="output"></div>