I'm nesting custom elements. I'd like to have my parent custom element use methods and properties from its child custom element's prototype. E.g.
<script>
var ChildElement = Object.create(HTMLElement.prototype);
ChildElement.getName = function () {
return "Bob";
}
document.registerElement("child-element", {
prototype: ChildElement
});
var ParentElement = Object.create(HTMLElement.prototype);
ParentElement.createdCallback = function () {
var self = this;
setTimeout(function () {
// This logs 'Bob', correctly
console.log(self.childNodes[0].getName());
}, 0);
// This explodes - getName is not defined.
console.log(self.childNodes[0].getName());
};
document.registerElement("parent-element", {
prototype: ParentElement
});
</script>
<parent-element><child-element></child-element></parent-element>
As noted inline, the parent cannot read anything that's defined on the child's element's prototype. It can if it fires an immediate setTimeout though; it just needs to wait until the child nodes of this element have also been set up.
It appears this happens because of the callback order during element creation, which I think is something like:
That the createdCallback fires at this point makes sense, but as far as I can tell there's no callbacks available at all that fire when all your children have been created. I think that means it's impossible to ever do anything on creation that uses the prototype of your child elements, without using setTimeout to wait for the entire page to finish rendering.
Are there any callbacks or events you can listen to from the parent, to trigger only once the prototype of all your child nodes has also been set? Is there a different approach that would allow you to use structures like this? Is there anything else you can do, other than trigger a setTimeout?
I believed custom elements were designed to allow parameterization with other element content, and having custom elements effectively not supported in that content is quite surprising.
Arguably this could be considered a duplicate of Prototype not defined when accessing children on creation of custom-tag. However that question is poorly phrased, with broken examples, and the only answer appears to actually be an implementation bug, not a solution (or at least, it's no longer current browser behaviour)
The customElements. get() method can be used to check whether a given custom element has already been registered in the page. This can be used to find whether a given custom element name is available in the page or not, and prevent clashes with another custom element.
The functionality of a custom element is defined using an ES2015 class which extends HTMLElement . Extending HTMLElement ensures the custom element inherits the entire DOM API and means any properties/methods that you add to the class become part of the element's DOM interface.
Actually, there are many different ways to achieve this with nested custom elements.
The direct way is to add a custom callback to the parent element that will be called by the child element from its attachedCallback
method:
ParentElement.childAttachedCallback = function ()
{
console.log( this.childNodes[0].getName() )
}
ChildElement.attachedCallback = function()
{
this.parentElement.childAttachedCallback()
}
In a complex scenario you could use instead:
Promise
object set by the parent and resolve by one or more childs,MutationObserver
object set to observe changes in the parent's child list... If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With