How to conditionally render slotted content #3843
-
Is there a way to prevent a component from rendering, if a parent component decides it's not the time yet? I am not just talking about visual rendering, but the goal is to have the element completely ignored. As an example, for dialogs I would like to only render the contents when the given dialog is visible/opened. <some-dialog
?opened=${false}
>
<some-other-element>
I am doing async stuff, so please don't actually render me unless some-dialog is open.
</some-other-element>
</some-dialog> So far what I have found, even when you remove the slot element (within To be specific, the following implementation for class SomeDialog {
static properties = {
opened: { type: Boolean, reflect: true },
};
render() {
if (!this.opened) {
return ''; // slot may be gone, but any childs are still 'called' or 'rendered'
}
return html`
<slot></slot>
`;
}
} Is there a (natural) way to do this?
Thanks for any input! |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 3 replies
-
Slotted elements belong to the outer scope of a host with a shadow root, so their connected-ness isn't controlled by the host, it's controlled by whatever put them there. Like you noted, removing the slot doesn't remove the element. Since the slot is an implementation detail of the host, this DOM: <some-dialog>
<some-other-element></some-other-element>
</some-dialog> ...doesn't change regardless of the presence of slots in This is the same for a native detail element. The content is not detached, it's just not rendered. If you want to know when the content is displayed, you can listen for the I think there are two (maybe 3) main ways to handle this:
html`
<some-dialog .opened=${opened}>
${opened
? html`
<some-other-element>
I am doing async stuff, so please don't actually render me unless some-dialog is open.
</some-other-element>`
: nothing}
</some-dialog>
`
html`
<some-dialog .opened=${opened}>
<some-other-element ?disabled=${!opened}>
I am doing async stuff, so please don't actually render me unless some-dialog is open.
</some-other-element>
</some-dialog>
`
I haven't tried this myself, but IntersectionObserver may be able to tell if the element is displayed. This would help not make API calls when the element is offscreen too. |
Beta Was this translation helpful? Give feedback.
-
I faced a reverse problem to this one. I have a slot with a fallback content, and I expected that if the slot content is provided, fallback elements should not be connected to the dom at all, but they are. For now I remove fallback content in the slotchanged event handler (only called if the slotted content is provided) |
Beta Was this translation helpful? Give feedback.
Slotted elements belong to the outer scope of a host with a shadow root, so their connected-ness isn't controlled by the host, it's controlled by whatever put them there. Like you noted, removing the slot doesn't remove the element.
Since the slot is an implementation detail of the host, this DOM:
...doesn't change regardless of the presence of slots in
<some-dialog>
.This is the same for a native detail element. The content is not detached, it's just not rendered. If you want to know when the content is displayed, you can listen for the
toggle
event.I think there are two (maybe 3) main ways to handle this: