Note that there are some explanatory texts on larger screens.

plurals
  1. POMeteorjs nested conditional templates
    text
    copied!<p>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?</p> <p>Client.js</p> <pre class="lang-js prettyprint-override"><code>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()); }); }); } </code></pre> <p>Client.html</p> <pre class="lang-html prettyprint-override"><code>&lt;head&gt; &lt;title&gt;conditional templates&lt;/title&gt; &lt;/head&gt; &lt;body&gt; {{&gt; main }} &lt;/body&gt; &lt;template name="main"&gt; &lt;section id="container"&gt;&lt;/section&gt; &lt;/template&gt; &lt;template name="foo"&gt; &lt;h2&gt;Foos&lt;/h2&gt; {{ contents }} &lt;/template&gt; &lt;template name="bar"&gt; &lt;h2&gt;Bars&lt;/h2&gt; {{ contents }} &lt;/template&gt; </code></pre> <p>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:</p> <p>html</p> <pre class="lang-html prettyprint-override"><code>&lt;template name="main"&gt; {{ contents }} &lt;/template&gt; </code></pre> <p>js</p> <pre class="lang-js prettyprint-override"><code>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. </code></pre> <p>There are two gotchas with this which might make it less than ideal.</p> <ol> <li>Any nested templates rendered inside the main template must also be marked as SafeString. Otherwise the contents will be escaped by Handlebars. This could lead to some bloat as the SafeString code is needed for every nested template.</li> <li>By marking a string as safe, i.e. unescaped, the onus is now on the developer to remember to escape any potentially unsafe strings before inserting them into the page. The more of these you have, the more likely you'll create a security hole. (See <a href="http://handlebarsjs.com/" rel="nofollow">http://handlebarsjs.com/</a> for documentation)</li> </ol> <p>So, in my mind, the question is still open. But I will defer to an editor.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload