I have a reference to an element that will at some point be upgraded to a custom element. How do I wait for it to be upgraded?
For example, suppose el
is the reference. If it hypothetically had a promise attached to it for this purpose, code could be similar to
await el.upgradePromise
// do something after it has been upgraded.
That of course doesn't exist, but describes what I want to do. Maybe there is no way to do it without polling? If I use polling, what would I poll for (suppose I don't have a reference to the class constructor that it should upgrade to). Maybe I can poll el.constructor
and wait for it not to be HTMLElement
, or wait for it not to be HTMLUnknownElement
?
EDIT: for background, I have some code like the following, where using setTimeout is a hack in order for the code to work. The first console.log
outputs false, while the one in the timeout outputs true.
import OtherElement from './OtherElement'
class SomeElement extends HTMLElement {
attachedCallback() {
console.log(this.children[0] instanceof OtherElement) // false
setTimeout(() => {
console.log(this.children[0] instanceof OtherElement) // true
}, 0)
}
}
where OtherElement
is a reference to a Custom Element class that will at some point be registered. Note, I'm using Chrome v0 document.registerElement
in my case. The timeout is needed because if SomeElement
is registered first as in the following code, then OtherElement
will not yet be registered, so therefore if the child of the SomeElement
element is expected to be an instance of OtherElement
, then that will not be the case until those elements are upgraded next.
document.registerElement('some-el', SomeElement)
document.registerElement('other-el', OtherElement)
Ideally, a timeout like that is undesirable, because if upgrade happens to take a longer time (for some unknown reason that could depend on the browser implementation) then the timeout hack will also fail.
I'd like an absolute way to wait for something to be upgraded without possible failure, and without polling if possible. Maybe it needs to be canceled after some time too?
EDIT: The ideal solution would allow us to wait for the upgrade of any third-party custom elements without needing to modify those elements before runtime, and without having to monkey patch then at runtime.
EDIT: From observing Chrome's v0 behavior, it seems like the first call to document.registerElement('some-el', SomeElement)
causes those elements to be upgraded and their attachedCallback
methods to be fired before the registration of OtherElement
, so the children will not be of the correct type. Then, by deferring logic, I can run logic after the children have also been upgraded to be of type OtherElement
.
EDIT: Here's a jsfiddle that shows the problem, and here's a jsfiddle that shows the timeout hack solution. Both are written with Custom Elements v1 API in Chrome Canary, and won't work in other browsers, but the problem is the same using Chrome Stable's Custom Elements v0 API with document.registerElement
and attachedCallback
instead of customElements.define
and connectedCallback
. (See console output in both fiddles.)