Reputation: 1910
It is possible to render different templates and place them inside a container template by re-rendering when a session variable changes and then directly manipulating the DOM. However, this doesn't feel like the Meteor way. Is there an idiomatic way of handling the DOM update?
Client.js
if (Meteor.isClient) {
var getContainerContents = function() {
console.info('get container contents');
var active = Session.get('active') == 'foo' ? 'foo' : 'bar';
return Meteor.render(Template[active]());
};
Template.foo.contents = function() {
console.info('foo contents');
return 'The foos.';
};
Template.bar.contents = function() {
console.info('bar contents');
return 'The bars.';
};
Meteor.startup(function() {
console.info('startup');
Meteor.autorun(function() {
console.info('autorun');
$('#container').html(getContainerContents());
});
});
}
Client.html
<head>
<title>conditional templates</title>
</head>
<body>
{{> main }}
</body>
<template name="main">
<section id="container"></section>
</template>
<template name="foo">
<h2>Foos</h2>
{{ contents }}
</template>
<template name="bar">
<h2>Bars</h2>
{{ contents }}
</template>
Update: It's possible to use template helpers for this purpose as well. The solution is to return the un-rendered string contents from the template() function and mark them as safe in Handlebars like so:
html
<template name="main">
{{ contents }}
</template>
js
var getContainerContents = function() {
console.info('get container contents');
var active = Session.get('active') == 'foo' ? 'foo' : 'bar';
return Template[active]();
};
Template.main.contents = function() {
return new Handlebars.SafeString(getContainerContents());
};
// Remove the startup and autorun code. Not necessary now.
There are two gotchas with this which might make it less than ideal.
So, in my mind, the question is still open. But I will defer to an editor.
Upvotes: 4
Views: 4030
Reputation: 3594
You car reference a template using its name stored in an exposed variable (in template helper):
{{> Template.dynamic template=varHandlingTemplateName }}
This is the way meteorjs resolve dynamic template situations in its latest version (as of today).
Regards, Greg
Upvotes: 0
Reputation: 119
this is the setup i'm using
client/client.js
Template.page.display_content = function () {
var page_index = Handlebars.Utils.escapeExpression(Session.get('page'));
if (Template[page_index]) {
return Template[page_index]();
} else {
return Template['page_not_found']();
}
};
client/template.html
<template name="page">
{{{display_content}}}
</template>
i just have to do Session.set("page", "xyz") to change pages and because of the {{{ it's automatically marked as SafeString.
to 1. Nested templates inside the template "xyz" don't need to be marked as SafeString, they are all rendered before it is escaped
to 2. You don't have to, because if you output some data like {{text}} it is again automatically escaped, it just won't get escaped again
Upvotes: 1
Reputation: 1491
Use Handlebars conditionals:
<template name="main">
{{#if active}}
{{> foo}}
{{else}}
{{> bar}}
{{/if}}
</template>
In your Meteor JavaScript code:
Template.main.active = function () {
return Session.get("active");
}
If both foo and bar share contents, you could either either use a Helper, or have both foo and bar use the same partial (ie.
{{> contents}}
) depending on your need.
Upvotes: 3