Search code examples
google-closure-templates

How can I append soy template return values as DOM nodes to the document body?


I am currently appending Google Closure Soy templates to the body of my HTML document via

var header = app.ui.templates.home.header();
document.body.innerHTML =
  header + app.ui.templates.home.bottom({
      "widgets": widgets,
  });

However, I don't believe this is optimal since soy template constructors do not return DOM nodes. Hence, I cannot say call goog.dom.appendChild(header, someNewElementICreated);.

Is there a convenient way to convert a soy template (say header) into a DOM node? I could just call goog.dom.$('idOfMyHeader'), but that would involve a browser reflow operation since a new DOM node is appended to the header after the header has already been displayed.


Solution

  • Is there a convenient way to convert a soy template (say header) into a DOM node?

    Closure Templates can be rendered as DOM fragments using the Soy JavaScript library function soy.renderAsFragment.

    app.js

    goog.require('app.ui.templates');
    goog.require('soy');
    
    var fragment = soy.renderAsFragment(app.ui.templates.myTemplate, null /*data*/);
    goog.dom.appendChild(goog.dom.getElementsByTagNameAndClass('body')[0],
        /** @type {Node} */ (fragment));
    

    templates.soy

    {namespace app.ui.templates}
    
    {template .myTemplate}
      <div>
        ...
      </div>
    {/template}
    

    Since the rendered template in this case is an Element Node, it may be cast to a Node and appended to the DOM. However, it is more common to use div elements as placeholders and setting the innerHTML attribute.