Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamically loading templates in Meteor.js

I would like the ability to load templates dynamically without explicitly specifying the template.

As an example:

<template name="foo">
</template>

where 'foo' is the template, I would like the ability to load it dynamically by calling some method:

Meteor.render(Meteor.loadTemplate('foo'));

Is this possible?

like image 582
chimon2000 Avatar asked Oct 19 '12 06:10

chimon2000


4 Answers

Here's how to dynamically render templates, as of Meteor 0.9.4 - 1.0. All other answers were obsolete at the time of this writing.

Let's say you're editing a bunch of records, or creating a new one, and want to render either the update template, or the new template, based on some Session variables.

There are two ways to do this:

1) This is the officially recommended method for Meteor 0.9.4 or newer - it uses Template.dynamic:

<template name="records">
  {{> Template.dynamic template=whichOne}}
</template>

<template name="recordUpdate">
  ...
</template>

<template name="recordNew">
  ...
</template>

Template.records.helpers({
  whichOne: function () {
    return Session.get('edit') ? 'recordUpdate' : 'recordNew'
    // note that we return a string - per http://docs.meteor.com/#template_dynamic
  }
});

2) This works in various Meteor versions, but isn't recommended officially because it's unclear that the template is chosen dynamically:

<template name="records">
  {{> whichOne}}
</template>

{{! Note how "whichOne" is indistinguishable from a constant template name... }}
{{  ...like "recordUpdate" or "recordNew" below. }}

<template name="recordUpdate">
  ...
</template>

<template name="recordNew">
  ...
</template>

Template.records.helpers({
  whichOne: function () {
    return Session.get('edit') ? Template.recordUpdate : Template.recordNew
    // note that we return a Template object, not a string
  }
});

To pass a data context to the template, use:

{{> Template.dynamic template=whichOne data=myData}}
like image 105
Dan Dascalescu Avatar answered Oct 31 '22 11:10

Dan Dascalescu


Meteor 0.9.x New API

Dan Dascalescu pointed out Meteor now has built-in dynamic templates! This is nice because you do not need to include the extra code as seen in previous versions.

{{> Template.dynamic template=template [data=data] }}

For Meteor 0.8.x Legacy

Dynamic Template Without Data: Boris Kotov's updated Blaze (0.8.0) answer is on the right track (taken from the latest docs), but it doesn't work as-is for me. I got the following to work:

{{> dynamicTemplate name=myDynName}}

<template name="dynamicTemplate">
    {{#with chooseTemplate name}}
        {{> template}}
   {{/with}}
</template>

Template.dynamicTemplate.chooseTemplate = function (name) {
    return { template: Template[name] };
};

I hope there is a simpler solution, but I needed to wrap the Template in a JSON as shown. Maybe this will help someone else to move forward.

Dynamic Template With Data: If you have and want data to be dynamic, be sure to make a helper method that can react. Be sure to do a Session.set() somewhere to see the effect.

// Inside "myContainingTemplate"
{{> dynamicTemplateWithData name=myDynName data=myDataHelper}}

<template name="dynamicTemplateWithData">
    {{#with chooseTemplate name}}
        {{#with ../data}}
            {{> ..}}
        {{/with}}
    {{/with}}
</template>

Template.dynamicTemplateWithData.chooseTemplate = function (name) {
    return Template[name];
};

Template.myContainingTemplate.helpers({
    myDataHelper: function () {
        Session.get('myReactiveKey');
    }
});
like image 34
Turbo Avatar answered Oct 31 '22 11:10

Turbo


You have found Meteor.render but what you are missing is the template loading. In the docs it mentions that you can call Template.foo() to return the HTML for a template.

http://docs.meteor.com/#template_call

Putting that together you access the template foo or any other using bracket access so:

var templateName = "foo";
var fragment = Meteor.render( function() {
    return Template[ templateName ](); // this calls the template and returns the HTML.
});

Then fragment is your Reactive fragment, so that your template can continue to receive live updates. Your fragment now needs placing in the web page (I use jQuery, so this example does as well):

$("#htmlnode").html( fragment );

$("#htmlnode") is just a node in your DOM where you want the template rendered. And you now have the rendered content in your web page.

like image 26
Joc Avatar answered Oct 31 '22 10:10

Joc


I'm just doing it like this, no jQuery required:

EDITED

Template.mainContent.showContentFromRouter = function() {
    return Template[Meteor.Router.page()]();
};

In this case I'm using the Meteor Router, and return whatever template that I choose to (from the Router), but you could just do this:

Template.mainContent.showDynamicContent = function() {
    return Template['someTemplateYouveDefined']();
};
like image 2
Kristoffer K Avatar answered Oct 31 '22 12:10

Kristoffer K