Search code examples
jquery-templatesjsrender

Dynamically assigning different templates based on data - using helper or custom tag


I render a jsrender template in template object.

var colorTmpl = {
     "color": jQuery.templates("<span>{{:~val}}</span>"),
}
var jsrendertmpl = {};
jQuery.extend(jsrendertmpl, colorTmpl);

If I access the jsrendertmpl.colorTmpl.render() it will render the color template. If I include this tmpl template tag within other template like this

{colorArr: ["white", "blue", "black"]}

{{for colorArr tmpl="jsrendertmpl.colorTmpl"/}} 

It will not include that subtemplate into parent template. So I add a custom tag to include this subtemplate within object

includetmpl: function(tmplname){
            return Template.render(tmplVal, jObj);
},

If I include the subtemplate in parent template {{:~val}} cannot be recognised

Parent Template with customised include tag

{{for colorArr itemVar='~val'}}
      {{includetmpl "color"}}
{{/for}}

Parent template without subtemplate (It works fine)

{{for colorArr itemVar='~val'}}
      <span>{{:~val}}</span>
{{/for}}

Is there any way to access that value. I used a {{setvar}} and {{:~getvar}} for workaround but need a permanent solution.

Thanks in advance.


Solution

  • There are a few ways you can implement that scenario - i.e. to provide different templates based on a data parameter that you pass in.

    For example you can pass in the template as a helper:

    $.views.helpers("myTemplates", {
        color: $.templates("<span>{{:}}</span>"),
        colorVal: $.templates("<span>{{:~val}}</span>")
    });
    

    And use it as in

    {{for colorArr tmpl=~myTemplates.color/}}
    

    or if tmplVar is your chosen template: "color"

    {{for colorArr tmpl=~myTemplates[tmplVar]/}}
    

    You can also create a custom tag, as you suggest, in either of the following ways:

    $.views.tags("includetmpl", {
        init: function(tagCtx) {
            this.template = myTemplates[tagCtx.props.template];
        }
    });
    

    or

    $.views.tags("includetmpl2", {
        render: function(val) {
            return myTemplates[this.tagCtx.props.template].render(val, this.ctx);
        }
    });
    

    (Note how I pass the context also to my render function, in the second version, so that ~val will be available...)

    Then use it as in the following:

    {{for colorArr}}{{includetmpl template="color"/}}{{/for}}
    

    or

    {{for colorArr itemVar="~val"}}{{includetmpl template="colorVal"/}}{{/for}}
    

    See https://jsfiddle.net/BorisMoore/coezx8xj/ for all of the above...

    I will change the title of your question to make it clearer.