-
Notifications
You must be signed in to change notification settings - Fork 0
Content Reprojection
Can you place a <content> element inside a component instance and have the component treat the reprojected content as if it were directly inside the component?
Your component can find many more applications if the component itself can be incorporated into other components. This raises the prospect that your component will need to deal with reprojected content. That term refers to DOM elements which have been picked up by one component's <content> element, and then picked up a second (or third, etc.) time by another <content> element.
As a trivial example, suppose you have a component that can return the number of top-level children it's currently displaying:
<polymer-element name="count-children">
<template>
<content></content>
</template>
<script>
Polymer({
get count() {
return this.children.length;
}
});
</script>
<polymer-element>
You envision this component of your being used directly in HTML like so:
<body>
<count-children>
<div>Child one</div>
<div>Child two</div>
<div>Child three</div>
</count-children>
</body>
When you get the child value of this instance, it will return the value 3, because the instance has three childen.
Now someone comes along who wants to develop a component that incorporates your child-counting component. They use your component inside their component to count only paragraph children.
<polymer-element name="count-paragraphs">
<template>
<count-children id="counter">
<content select="p"></content>
</count-children>
</template>
<script>
Polymer({
get count() {
return this.$.counter.count;
}
});
</script>
<polymer-element>
Now they use it so:
<body>
<count-paragraphs>
<h1>A heading</h1>
<p>Paragraph one</p>
<p>Paragraph two</p>
<p>Paragraph three</p>
</count-paragraphs>
</body>
If you get the count value of this component, the answer is unexpected: it's always 1. That's because, in this situation, your count-children component always contains a single element: the <content> element defined by <count-paragraphs>.
<count-children id="counter">
<content select="p"></content>
</count-children>
To <count-children>, the value of its children property is an element list containing just the <content> element. So the answer of 1 here is technically correct, but probably not expected. Rather, the intention here was probably to have <count-children> look inside the <content> element and count what it finds there. And if that content contains a <content> element, counting should probably continue going deeper.
What's really wanted is a way to traverse the complete set of children, including any degree of reprojection.
# TODO: Verify that this works
get count() {
total = 0;
Array.prototype.forEach.call(this.children, function(child) {
if (child instanceof HTMLContentElement) {
count += child.getDistributedNotes().length;
} else {
count++;
}
});
return total;
}