I'd like to inject a rendering template from a parent component to a child component using <slot>
insertion points. The injected template contains data-binding on a property of the child component (my-child.data
in this case).
<dom-module id="my-parent">
<template>
<my-child>
<template>
<div>Child's data property: [[data]]</div>
</template>
</my-child>
</template>
...
The rendering child component basically looks like this:
<dom-module id="my-child">
<template>
<header></header>
<slot></slot>
<footer></footer>
</template>
<script>
class MyChild extends Polymer.Element {
static get is() { return 'my-child'; }
static get properties() {
return {
data: { ... }
};
}
...
I'm not sure whether this is possible at all with Polymer2. Vue2 has a concept called "scoped slot" to achieve this. Thanks in advance for any feedback!
Data binding is by default tied within the current scope of the binding. If you wish to change the scope, you must put your markup inside a <template>
tag and stamp in it inside a different scope.
Your HTML code in the question is already OK - you actually wrap the light DOM inside a <template>
, but you then use that <template>
incorrectly. You must not use <slot>
, but must stamp that template manually and insert it somewhere inside the my-child
element's shadow DOM.
Here you have a working demo on how to achieve this: http://jsbin.com/loqecucaga/1/edit?html,console,output
I have even added the data
property binding to an input
element in order to demonstrate that property changes also affect the stamped template.
The stamping is relatively simple and is done inside the connectedCallback
method:
var template = this.querySelector('template');
this.__instance = this._stampTemplate(template);
this.$.content.appendChild(this.__instance);
The stamped template is put inside a placeholder div
element, which you put somewhere inside the my-child
's template:
<div id="content"></div>
To sum up, here is the full code from the demo:
<link href="polymer/polymer-element.html" rel="import"/>
<link href="polymer/lib/mixins/template-stamp.html" rel="import"/>
<dom-module id="my-parent">
<template>
<my-child>
<template>
<div>Child's data property: [[data]]</div>
</template>
</my-child>
</template>
<script>
class MyParent extends Polymer.Element {
static get is() { return 'my-parent'; }
}
window.customElements.define(MyParent.is, MyParent);
</script>
</dom-module>
<dom-module id="my-child">
<template>
<header>Header</header>
<div id="content"></div>
<footer>Footer</footer>
<input type="text" value="{{data::input}}" />
</template>
<script>
class MyChild extends Polymer.TemplateStamp(Polymer.Element) {
static get is() { return 'my-child'; }
static get properties() {
return {
data: {
type: String,
value: 'Hello, World!'
},
};
}
connectedCallback() {
super.connectedCallback();
var template = this.querySelector('template');
this.__instance = this._stampTemplate(template);
this.$.content.appendChild(this.__instance);
}
}
window.customElements.define(MyChild.is, MyChild);
</script>
</dom-module>
<my-parent></my-parent>