Search code examples
javascripthandlebars.js

How do I load different partials dynamically using handlebars templates?


I'm loading a template with the following data:

"slides": [
    {
        "template": "video",
        "data": {
            "video": ""
        }
    },
    {
        "template": "image",
        "data": {
            "image": ""
        }
     }
]

in my template I want to loop over these slides and based on the configured template I want to load a partial

{{#each slides}}
    {{> resources_templates_overlay_video }}
{{/each}}

How can I make this partial load dynamically (based on the configured template)?

I'm using the require-handlebars-plugin


Solution

  • As far as I can tell, hbs expects the partials to be known at compile time, which is way before you pass in your data. Let's work around that.

    First, pull in your dynamic partials before rendering, something like:

    // I required the main template here for simplicity, but it can be anywhere
    var templates = ['hbs!resources/templates/maintemplate'], l = data.slides.length;
    for (var i=0; i<l; i++ )
        templates.push('hbs!resources/templates/overlay/'+data[i].template);
    
    require(templates, function(template) {
        var html = template(data);
    });
    

    And define a helper that will act as a dynamic partial

    define(['Handlebars'], function (Handlebars) {
    
        function dynamictemplate(template, context, opts) {
            template = template.replace(/\//g, '_');
            var f = Handlebars.partials[template];
            if (!f) {
                return "Partial not loaded";
            }
    
            return new Handlebars.SafeString(f(context));
        }
    
        Handlebars.registerHelper('dynamictemplate', dynamictemplate);
        return dynamictemplate;
    });
    

    Finally, modify your main template to look like

    {{#each slides}}
        {{dynamictemplate this.template this.data}}
    {{/each}}