Как я могу сделать визуализацию с соевыми шаблонами?
У меня есть этот шаблон сои
{template .myRowTemplate}
<tr><td>Hello</td></tr>
{/template}
и я хочу сделать что-то вроде
var myTable = goog.dom.createElement("table");
goog.dom.appendChild(myTable, goog.soy.renderAsFragment(mytemplates.myRowTemplate));
goog.dom.appendChild(myTable, goog.soy.renderAsFragment(mytemplates.myRowTemplate));
Но это вызывает
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>
Какой лучший способ сделать это?
1 ответ
Почему это не удается
Правильно, документация renderAsFragment
немного сбивает с толку; это читает:
Визуализирует шаблон сои в один узел или фрагмент документа. Если представленная HTML-строка представляет один узел, то этот узел возвращается
Однако (упрощенная) реализация renderAsFragment
является:
var output = template(opt_templateData);
var html = goog.soy.ensureTemplateOutputHtml_(output);
goog.soy.assertFirstTagValid_(html); // This is your failure
var safeHtml = output.toSafeHtml();
return dom.safeHtmlToNode(safeHtml);
Так почему автор замыкания утверждает, что первый тег не <tr>
?
Это потому, что внутри safeHtmlToNode
мест safeHtml
во временном div
, прежде чем решить, если он должен вернуть div
wrappper (общий случай) или единственный дочерний элемент (если отображаемый HTML-код представляет только один узел). Еще раз упростил код safeHtmlToNode
является:
var tempDiv = goog.dom.createElement_(doc, goog.dom.TagName.DIV);
goog.dom.safe.setInnerHtml(tempDiv, html);
if (tempDiv.childNodes.length == 1) {
return tempDiv.removeChild(tempDiv.firstChild);
} else {
var fragment = doc.createDocumentFragment();
while (tempDiv.firstChild) {
fragment.appendChild(tempDiv.firstChild);
}
return fragment;
}
renderAsElement также не будет работать
И я не уверен, что вы просите фрагменты, но, к сожалению, goog.soy.renderAsElement()
будет вести себя так же, потому что он также использует временный div
сделать DOM.
renderElement не может зациклить
Сообщение об ошибке предлагает goog.soy.renderElement
, но это будет работать только в том случае, если ваша таблица имеет одну строку, поскольку она заменяет контент и не добавляет дочерние узлы.
Рекомендуемый подход
Так обычно мы делаем цикл for в шаблоне:
{template .myTable}
<table>
{foreach $person in $data.persons}
<tr><td>Hello {$person.name}</td></tr>
{/foreach}
</table>
{/template}
Конечно, мы можем сохранить простой шаблон для одной строки и call
это из большего шаблона.