11

我希望使用聚合物和飞镖制作一个通用列表。我正在扩展 UL 元素来做到这一点。我想在这个自定义元素的内容中放置模板变量。

<ul is="data-ul">
  <li>{{item['first_name']}}</li>
</ul>

自定义元素

<polymer-element name="data-ul" extends="ul">
  <template repeat="{{item in items}}">
      <content></content>
  </template>
  <script type="application/dart" src="data-ul.dart"></script>
</polymer-element>

我期待模板变量被插值,但它只是按原样输出到 DOM。如何输出内容标签以呈现为模板,而不仅仅是直接输出?

4

2 回答 2

10

不幸的是,这里有两个问题。

  1. <content>不能这样使用。它是一个占位符,用于在 Shadow DOM 中的特定位置渲染轻量级 DOM 节点。<content>选择节点的第一个获胜 [ 1 ]。像您正在做的那样冲压出一堆,虽然非常直观,但不会按预期工作。

  2. 您将 Polymer 的内部世界与元素外部的外部世界混合在一起。这真正意味着绑定(例如{{}})仅在<polymer-element>.

您可以做的一件事是创建分布式轻量级 DOM 子级的副本作为items元素的属性。在 JavaScript 中,这看起来像:

<template repeat="{{item in items}}">
  <li>{{item['first_name']}}</li>
</template>
<content id="content" select="li"></content>
<script>
  Polymer('data-ul', {
    ready: function() {
      this.items = this.$.content.getDistributedNodes();
    }
  });
</script>

注意:我使用的唯一原因<content select="li">是确保元素只接收<li>节点。如果您不担心用户使用其他类型的元素,只需使用this.items = [].slice.call(this.children);.

于 2013-12-22T17:03:54.227 回答
1

为此,您应该覆盖该parseDeclaration方法。该方法负责解析/创建需要绑定的 html。例如,假设您有下一个模板

<polymer-element name="data-ul" extends="ul" attributes="items">
  <template>
    <template repeat="{{item in items}}" ref="itemTemplate"></template> <!-- this is the replacement of content tag -->
  </template>
  <script type="application/dart" src="data-ul.dart"></script>
</polymer-element>

或者,如果您想要一些默认元素:

<polymer-element name="data-ul" extends="ul" attributes="items">
  <template>
    <template repeat="{{item in items}}">
      <!-- Def elements -->
      <template bind="{{item}}" ref="itemTemplate"></template> <!-- this is the replacement of content tag -->  
      <!-- Def elements -->
    </template>
  </template>
  <script type="application/dart" src="data-ul.dart"></script>
</polymer-element>

那么你应该有下一节课:

@CustomTag('data-ul')
class DataUl extends LiElement with Polymer, Observable {
  DataUl.created() : super.created();

  @published List items;

  void parseDeclaration(Element elementElement) {
    // We need to remove previous template from element.templateContent
    // in that way it no continues adding a new content every time that we instantiate 
    // this component.
    var previousTemplate = element.templateContent.querySelector('template#item');
    if(previousTemplate != null)
      previousTemplate.remove();

    var t = this.querySelector('#itemTemplate'); // Gets the template with id itemTemplate from the content html
    if(t != null)  // if not null
      element.templateContent.append(t); // append itemTemplate to element.templateContent
    else 
      element.templateContent.append(new TemplateElement()..id='itemTemplate'); //if no template is added append an empty template to avoid errors


    super.parseDeclaration(elementElement); // call super
  }
}

最后使用自定义元素如下:

<ul is="data-ul" items="{{[{'first_name': 'jay'}, {'first_name': 'joy'}]}}">
  <template id="itemTemplate">
    <li>{{item['first_name']}}</li>
  </template>
</ul>
于 2014-11-12T16:34:12.887 回答