Отображение тега контента как части шаблона в полимере и дротике

Я хочу составить общий список, используя полимер и дротик. Я расширяю элемент 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 как есть. Как вывести тег контента, который будет отображаться в виде шаблона, а не только непосредственно выведенный?

Ответ 1

К сожалению, здесь есть две проблемы.

  • <content> нельзя использовать так. Это заполнитель для рендеринга светлых узлов DOM в определенных местах в Теневой DOM. Первый <content>, который выбирает узлы, выигрывает [1]. Выбирая кучу, как вы делаете, в то время как очень интуитивно понятный, не будет работать так, как ожидалось.

  • Вы смешиваете внутренний мир 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);.

Ответ 2

Для этого вы должны переопределить метод 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>