Description
Given
<vaadin-dialog no-close-on-outside-click no-close-on-esc draggable>
<template>
<entity-editor></entity-editor>
</template>
</vaadin-dialog>
and
@customElement('entity-editor')
export class EntityEditor extends LitElement {
connectedCallback() {
super.connectedCallback();
if (!this.hasAttribute('instance')) this.setAttribute('instance', '' + EntityEditor.instance);
EntityEditor.instance++;
console.log('Connected', this);
}
disconnectedCallback() {
super.disconnectedCallback();
console.log('Disconnected', this);
}
You will see the following in the log when opening the dialog
Connected <entity-editor instance="1">…</entity-editor>
Disconnected <entity-editor instance="1">…</entity-editor>
Connected <entity-editor instance="1">…</entity-editor>
and the following when closing it
Disconnected <entity-editor instance="1">…</entity-editor>
Connected <entity-editor instance="1">…</entity-editor>
As connectedCallback
is called after closing the dialog, any attempts to e.g. register global listeners in connectedCallback
and removing them in disconnectedCallback
will fail and the listeners will remain after the dialog is closed.
The reason for the extra events is that the <entity-editor>
element is first created inside <vaadin-dialog><vaadin-dialog-overlay>
and then <vaadin-dialog-overlay>
is moved to the <body>
element. After closing the dialog, the <vaadin-dialog-overlay>
element is moved back inside <vaadin-dialog>
.
It seems like the correct solution would be that <vaadin-dialog-overlay>
is never attached to <vaadin-dialog>
in the first place, nor moved back there.
Workaround:
connectedCallback() {
super.connectedCallback();
if (this.parentElement?.parentElement == document.body) {
// This is a real connect
this.connected = true;
document.body.addEventListener(...)
}
}
disconnectedCallback() {
super.disconnectedCallback();
if (this.connected) {
// This is a real disconnect
this.connected = false;
document.body.removeEventListener(...)
}
}