I've got this soy template
{template .myRowTemplate}
<tr><td>Hello</td></tr>
{/template}
and I want to do something like
var myTable = goog.dom.createElement("table");
goog.dom.appendChild(myTable, goog.soy.renderAsFragment(mytemplates.myRowTemplate));
goog.dom.appendChild(myTable, goog.soy.renderAsFragment(mytemplates.myRowTemplate));
But that causes
Uncaught goog.asserts.AssertionError
Assertion failed: This template starts with a <tr>,
which cannot be a child of a <div>, as required by soy internals.
Consider using goog.soy.renderElement instead.
Template output: <tr><td>Hello</td></tr>
What's the best way to do this?
Why it fails
Right, the documentation of
renderAsFragmentis a bit confusing; it reads:However, the (simplified) implementation of
renderAsFragmentis:So why do the closure author assert that the first tag is not
<tr>?That's because, internally,
safeHtmlToNodeplacessafeHtmlin a temporarydiv, before deciding if it should return thedivwrappper (general case) or the only child (if the rendered HTML represents only one Node). Once again simplified, the code ofsafeHtmlToNodeis:renderAsElement won't work either
And I'm unsure what you are asking for fragments, but unfortunately
goog.soy.renderAsElement()will behave the same because it also uses a temporarydivto render the DOM.renderElement cannot loop
The error message suggests
goog.soy.renderElement, but that will only work if your table has one row, since it replaces content, and doesn't append children nodes.Recommended approach
So usually, we do the for loop in the template:
Of course, we can keep the simple template you have for one row and
callit from the larger template.