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