Reputation: 33
In the code below, the content "Foo" of template#bar are always empty when I try to access it programatically or when inspecting the DOM in Chrome. Can someone explain why?
In general, how does one provide a template defined in an outer element to an inner element so the inner element can access the content and conditionally clone or import that content?
I am using polymer 0.4.2.
<polymer-element name="x-inner" noscript>
<!--
How can I access the content "Foo" of <template>Foo</template>,
So that I can import/clone it here?
Using <content> moves the template from x-outer to x-inner,
but the template's .content property is empty, instead of 'Foo' as I expected.
-->
<content></content>
</polymer-element>
<polymer-element name="x-outer" noscript>
<template>
<x-inner>
<!--
How can I pass a template to a custom element?
I don't want the contents of this template to be rendered
here in x-outer, but instead conditionally rendered by x-inner
-->
<template id="bar">Foo</template>
</x-inner>
</template>
</polymer-element>
<x-outer></x-outer>
Upvotes: 3
Views: 1283
Reputation: 11027
This topic is potentially complicated, below is something to get you started.
(This is the third update to this answer, confirming the bit above about 'complicated' =P).
Polymer includes the TemplateBinding.js
library.
The TemplateBinding.js
library imbues <template>
with numerous features, including data-binding to models, conditional stamping, and replication/iteration via arrays. It also adds a feature whereby cloned nested templates do not replicate their own contents, preventing a possible explosion of useless nodes when iterating. Instead, TemplateBinding.js
creates references in cloned-nested-templates to original content-ful templates. The upshot is that if you are using TemplateBinding.js
you should use template.createInstance()
API for best results.
Now, when using raw templates without TemplateBinding.js
, you can stamp a template simply using var nodes = document.importNode(template.content, true)
. Of course, in this case you do not get the nested template replication optimization (which may or may not matter).
Note:
<content>
node from the <x-inner>
template because it serves no purpose. The code below plucks the
template directly out of light-dom, and stamps the instance into the
shadow-root.x-inner
before x-outer
because the latter depends on the former.Example code:
<x-outer></x-outer>
<polymer-element name="x-inner">
<template>
</template>
<script>
Polymer({
domReady: function() {
this.renderTemplate();
},
renderTemplate: function() {
// note: this only works if `template` is a true child of `this`
// (as opposed to projected)
var template = this.querySelector('template');
// use createInstance from TemplateBinding.js library API
this.shadowRoot.appendChild(template.createInstance());
/*
// this would work for raw templates, but Polymer includes TemplateBinding.js
this.shadowRoot.appendChild(stampTemplate(template));
*/
/*
// if you don't know whether TemplateBinding.js exists or not,
// you could do something like this (see stampTemplate definition below)
this.shadowRoot.appendChild(stampTemplate(template));
*/
/*
// this way uses the binding feature of TemplateBinding.js
template.setAttribute('bind', '');
template.model = { /* some data */ };
*/
}
});
// use best available API
function stampTemplate(template) {
if (template.createInstance) {
return template.createInstance();
} else {
return document.importNode(template.content, true);
}
}
</script>
</polymer-element>
<polymer-element name="x-outer" noscript>
<template>
<x-inner>
<template id="bar">Foo</template>
</x-inner>
</template>
</polymer-element>
http://jsbin.com/nemaha/14/edit
Upvotes: 1