Search code examples
javascriptvariablesjsrender

What is a good way to create a variable in JsRender?


In a JsRender template, blocks can create variables, so I could write this:

{{if true ~myVariable=myExpensiveFunction()}}
  {{:~myVariable}} {{:~myVariable}}
{{/if}}

However, the bogus if is annoying. Is there a better way?


Solution

  • If you can initialize myVariable outside the template, then you can make it a helper variable, and pass it in:

    var html = myTmpl.render(data, {myVariable:myExpensiveFunction()});
    

    If you need to initialize in a specific template/data context then as you say, you can use contextual parameters, which are scoped to any template block. Use the tag that wraps that context.

    If the context is is top-level in a template, then:

    • either this is top-level data and you can pass in a helper as above
    • or it is a 'partial' template rendered from anothor (layout) template, using {{someTag tmpl=.../}}, in which case you can set up your contextual parameter from the calling tag in the other template
    • or else it is rendering against an array

    For that last case you can use {{include}}:

    {{include ~myVariable=myExpensiveFunction()}}
      {{:~myVariable}} {{:~myVariable}}
    {{/include}}
    

    or you can call with noIteration set to true:

    var html = myTmpl.render(data, [helpers,] true);
    

    and then wrap in {{for}}:

    {{for ~myVariable=myExpensiveFunction()}}
      {{:~myVariable}} {{:~myVariable}}
    {{/for}}
    

    EDIT:

    In your particular case, based on your comments added below, you need to initialize in the context of an item block within a {{for someArray}} - in order to get the item data.

    (Actually your item block is a 'partial' template called using {{for someArray tmpl=...}}, but the basic problem is the same).

    In this scenario you will indeed need to add an {{include}} wrapper, at top-level (for you) or within the {{for}} if not doing template composition.