I want to create a component which I can pass other components to and create DOM structures.
<test-component>
<img/>
<div/>
<foo/>
</test-component>
In trying to get that working:
<dom-module name="test-component">
<template>
<h1>Title</h1>
<ul>
<template is="dom-repeat" items="{{nodes}}">
<li>element:</li>
<li>{{item}}</li>
</template>
</ul>
<content id="contentelement"></content>
</template>
</dom-module>
<script type="text/javascript">
Polymer({
is: "test-component",
ready: function() {
this.nodes = (function(that) {
var nodeList = that.$.contentelement._distributedNodes,
nodeMap = [];
for(var i = 0; i < nodeList.length; i++) {
if(nodeList[i].nodeType === 1) {
nodeMap.push(nodeList[i].outerHTML);
}
}
return nodeMap
}(this));
}
});
</script>
I used a function to build this.nodes because this.nodes = this.$.contentelement.getDistributedNodes(); returns null, not sure why.
I know you can't just drop an element's outerHTML into the page but can a random set of HTML/components be passed into a template like this?
Unfortunately this is currently not possible with data-binding (have a look at this discussion on Github).
Here's a possible workaround in JavaScript.
<dom-module name="test-component">
<template>
<h1>Title</h1>
<ul>
<template is="dom-repeat" items="{{nodes}}">
<li>element:</li>
<li class="content"></li>
</template>
</ul>
<content id="contentelement"></content>
</template>
</dom-module>
<script type="text/javascript">
Polymer({
is: "test-component",
ready: function() {
this.nodes = this.getContentChildren();
this.async(function(){
var contentNodes = Polymer.dom(this.root).querySelectorAll(".content");
this.nodes.forEach(function(element, index) {
contentNodes[index].innerHTML = element.outerHTML;
});
}.bind(this));
}
});
</script>
Edit
You can remove the content nodes from their original location after you have accessed them by removing them from the DOM.
this.nodes = this.getContentChildren();
Polymer.dom(this.root).removeChild(this.$.contentelement);