I remember many web components tutorials say connectedCallback
is good for hooking up DOM events or getting some DOM elements (like this one). But I couldn't get a simple program to run in lit-element:
import { LitElement, html } from 'lit-element';
class MyElement extends LitElement {
render() {
return html`<p id="root">template content</p>`;
}
connectedCallback() {
super.connectedCallback();
this.shadowRoot.getElementById('root'); // null
}
firstUpdated() {
this.shadowRoot.getElementById('root'); // not null
}
}
Looks like it only works in firstUpdated
, doesn't firstUpdate
fire after first render? what if I need some events set up before first render? why connectedCallback
doesn't work here?
connectedCallback
works according to the spec, it just doesn't do what you expect.
Those callbacks fire at different moments in time
<my-element myattribute="foo"> 1. -> connectedCallback
<p id="root">
template content
</p>
</my-element> 2. -> firstUpdated (LitElement)
1. -> connectedCallback
means the Element is injected in the DOM.
but its children are not parsed yet.
Unless you use a FireFox (pre 2021 version!!), which fires connectedCallback
too late at 2. (confirmed bug)
Think of elements as water hoses; connect means the hose is connected to a tap, not that water flows through it. So you can access data-attributes (a property of the hose) in the connectedCallback
That is why the connectedCallback
fires at this 1. ->
moment in time... you may want content based on its attributes. And you don't want to wait for all content to be parsed (which potentially can be a very very large DOM tree)
Also note connectedCallback
runs every time you move the Element in the DOM
And if you dive deeper you will also notice attributeChangedCallback
runs before the connectedCallback
if you have observerAttributes on your element.
LitElement lifecycle callbacks are sugar, they 'safeguard' you against (powerful) bare metal Web Component behaviour.
So without LitElement, you can do:
connectedCallback(){
// 1. -> do stuff
setTimeout(() => {//no tricks, just wait till that dreaded JS Event Loop is done
// all children are parsed
// 2. -> do stuff
});
}
For gory callback details see: wait for Element Upgrade in connectedCallback: FireFox and Chromium differences