templatesmeteormeteor-blazespacebarsmeteor-helper

How can I dynamically render HTML using Meteor Spacebars templates?


So let's say I'm storing <div>{{name}}</div> and <div>{{age}}</div> in my database. Then I want to take the first HTML string and render it in a template - {{> template1}} which just renders the first string with the {{name}} handlebar in it. Then I want to give that newly generated template/html data, so that it can fill in the handlebar with the actual name from the database, so that we would get <div>John</div>. I've tried doing

<template name="firstTemplate">
    {{#with dataGetter}}
        {{> template1}}
    {{/with}}
</template>

Where template1 is defined as

<template name="template1">
    {{{templateInfo}}}
</template>

And templateInfo is the helper that returns the aforementioned html string with the handlebar in it from the database.

dataGetter is just this (just an example, I'm working with differently named collections)

Template.firstTemplate.dataGetter = function() {
    return Users.findOne({_id: Session.get("userID")});
}

I can't get the {{name}} to populate. I've tried it a couple of different ways, but it seems like Meteor doesn't understand that the handlebars in the string need to be evaluated with the data. I'm on 0.7.0 so no Blaze, I can't upgrade at the moment due to the other packages I'm using, they just don't have 0.8+ version support as of yet. Any ideas on how I can get this to work are much appreciated.


Solution

  • If you need to dynamically compile complex templates, I would suggest Kelly's answer.

    Otherwise, you have two options:

    1. Create every template variation, then dynamically choose the right template:

      eg, create your templates

      <template name="displayName">{{name}}</template>
      <template name="displayAge">{{age}}</template>
      

      And then include them dynamically with

      {{> Template.dynamic template=templateName}}
      

      Where templateName is a helper that returns "age" or "name"

    2. If your templates are simple, just perform the substitution yourself. You can use Spacebars.SafeString to return HTML.

      function simpleTemplate(template, values){
            return template.replace(/{{\w+}}/g, function(sub) {
                var p = sub.substr(2,sub.length-4);
                if(values[p] != null) { return _.escape(values[p]); }
                else { return ""; }
            })
      }
      Template.template1.helpers({
        templateInfo: function(){
            // In this context this/self refers to the "user" data
            var templateText = getTemplateString();
            return Spacebars.SafeString(
                simpleTemplate(templateText, this)
            );
        }