【问题标题】:How can I render a tr with soy templates?如何使用大豆模板渲染 tr?
【发布时间】:2017-02-01 23:39:01
【问题描述】:

我有这个大豆模板

{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>

最好的方法是什么?

【问题讨论】:

    标签: html google-closure-templates soy-templates


    【解决方案1】:

    为什么会失败

    对,renderAsFragment 的文档有点混乱;上面写着:

    将 Soy 模板呈现为单个节点或文档片段。如果呈现的 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);
    

    那么为什么闭包作者断言第一个标签不是&lt;tr&gt;

    这是因为,在内部,safeHtmlToNodesafeHtml 放在一个临时的 div 中,然后再决定它是否应该返回 div 包装器(一般情况)或唯一的孩子(如果呈现的 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 保留在较大的模板中。

    【讨论】:

    • 在推荐的方法中使用 $Person 代替 Person。
    猜你喜欢
    • 2016-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-30
    • 2012-06-13
    • 2014-01-25
    • 2013-04-07
    相关资源
    最近更新 更多