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>
[[data]]
within the<my-parent>
component template is always referred to itself and not the<my child>
element. Also I think there isn't a "scoped slot" Vue-like in Polymer 2. Why can't you print the[[data]]
directly inside your child component? – Impetus[[data]]
can be wrapped by various tags, e.g.<strong>[[data]]</strong>
or<code>[[data]]</code>
and I wanted to avoid distinct custom elements for each possibility or havingdom-if
blocks in themy-child
component being based on input properties to that component. In Polymer's legacy layer I still findtemplatizer-behavior
which seems to be deprecated. However I did not find any documentation about migration from Polymer 1.x to Polymer 2.x for template stamping. – Misereretemplate
and stamp it in a different scope. Yourmy-parent
element actually has the contents of themy-child
inside atemplate
element, which means you only need to stamp the template inside yourmy-child
. – Fante