Is there any way to reference a Handlebars inline partial programmatically?

Viewed 1156

Consider the following table template.hbs:

<table class="table table-striped table-hover">
    <thead>
        <tr>
            <th>Id</th>
            <th>Name</th>
            <th>Value</th>
        </tr>
    </thead>
    <tbody>
        {{#* inline "testTableRowTemplate"}}
        <tr>
            <td>{{Id}}</td>
            <td>{{Name}}</td>
            <td>{{Value}}</td>
        </tr>
        {{/inline}}
        {{#* inline "testTableEmptyTemplate"}}
        <tr>
            <td colspan="99">There are no rows</td>
        </tr>
        {{/inline}}
        {{#* inline "testTableLoaderTemplate"}}
        <tr>
            <td colspan="99">
                <i class="fa fa-spinner fa-spin fa-3x fa-fw"></i>
                <span class="sr-only">Loading...</span>
            </td>
        </tr>
        {{/inline}}
    </tbody>
</table>

From code, I am loading this template with an ajax call and compiling it to a HandlebarsTemplateDelegate which I use to dynamically refresh the table when new data is available. However, I would like to be able to target just a row, so I need a HandlebarsTemplateDelegate of just the "testTableRowTemplate" partial to be able to do this. Is there any way to do this from code? I've tried each of the following after compiling the main template but can't get access to the partial.

var rowPartial = Handlebars.partials["testTableRowTemplate"]; //doesn't work

And

var rowPartial = Handlebars.compile("{{>testTableRowTemplate}}"); //doesn't work

I'm hoping to avoid having multiple .hbs files for the table so ideally I'd be able to define reusable partials in the same file. Any ideas?

1 Answers

It does not appear that you can reference these from code. My workaround is as follows:

Table.hbs

You'll notice a make use of a custom helper registerPartial here. This allows me to dynamically register a handlebars helper.

<table class="table table-striped table-hover">
    <thead>
        <tr>
            <th>Id</th>
            <th>Name</th>
            <th>Value</th>
        </tr>
    </thead>
    <tbody>
        {{#registerPartial "testTableRowTemplate"}}
        <tr>
            <td>{{Id}}</td>
            <td>{{Name}}</td>
            <td>{{Value}}</td>
        </tr>
        {{/registerPartial}}
    </tbody>
</table>

Page.ts

At the page level, I define the helper registerPartial. It's important to note that this will be registered to the global Handlebars environment. Therefore all partial names need to be unique. This could be solved by declaring a Handlebars environment for each component, i.e. Table, List, etc. but that is beyond the scope of what I need.

Handlebars.registerHelper('registerPartial', (name, options) => Handlebars.registerPartial(name, options.fn));

Table.ts

Following loading the Table.hbs template by way of Handlebars.compile(templateContentFromTablehbs), I can now get compile references to the row partials by doing this:

this._rowTemplate = Handlebars.compile(`{{>${this._rowPartialName}}}`);

Now I can re-use this._rowTemplate to do partial refreshes of table rows without having to refresh the whole thing.

Related