javascripthandlebars.jshandlebarshelper

Applying a handlebar helper to another handlebar


I am trying to use Handlebars to return all distinct values in a column. The following Handlebars template returns all the values in the column "hostname" of my dataframe.

{{#each data}} {{"hostname.keyword"}} {{/each}}

This contains duplicate values and so I defined a helper to remove those duplicates.

handlebars.registerHelper("unique", (context) =>
  [...new Set(context)]);

I'm not able to figure out how to pass the result returned by the Handlebars #each block as an argument to the helper. For instance,

<div>{{unique ({{#each data}} {{"hostname.keyword"}} {{/each}})}}</div>

results in the following error:

    Parse error on line 2:
.../h5><div>{{unique ({{#each data}} {{"ho
----------------------^
Expecting 'ID', 'STRING', 'NUMBER', 'BOOLEAN', 'UNDEFINED', 'NULL', 'DATA', got 'OPEN_BLOCK'

The following does not produce any error, but it returns nothing:

<div>{{unique data "hostname.keyword"}}</div>

Is it possible to do this? And if so, what's the correct syntax?


Solution

  • I don't think there is a way to take the output of a block helper - like #each - and process it through an inline helper, like unique. What you would have to do instead is to have your custom helper do both the mapping of the objects to their value at the specified key (hostname.keyword) and then also filter the result set so as to have only unique values. Once you have the mapped and filtered result, you would pass that to the #each block helper.

    const template = Handlebars.compile('<div>{{#each (unique data "hostname.keyword")}}{{this}}{{/each}}</div>');
    
    Handlebars.registerHelper("unique", (context, key) => {
      return [...new Set(context.map(item => item[key]))];
    });
    
    const data = [
      {
        "hostname.keyword": "a"
      },
      {
        "hostname.keyword": "b"
      },
      {
        "hostname.keyword": "a"
      }
    ];
    
    const output = template({ data });
    
    document.body.innerHTML = output;
    console.log(output);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.7.7/handlebars.min.js"></script>