lit: wrap expensive dom in different tags

Viewed 166

I have an expensive list of DOM nodes in my <lit-parent> component, which under a certain condition (e.g. parent element width < 500px) needs to be wrapped in another component (e.g. a gallery):

render() {
    const expensive = this.vehicles.map(vehicle => html`<lit-vehicle id=${vehicle.id}?></vehicle>`);

    return this.someCondition ? html`<lit-gallery>${expensive}</lit-gallery>` : expensive;   
}

The problem is, every time the condition changes the list of expensive elements get's destroyed and re-created in the DOM, which causes the elements to flicker (I've tried combinations of cache and repeat neither changed the behaviour).

Instead I would like to re-use the already created DOM and just change (or remove) the wrapper.

The only way I found to somewhat make that work is to move the conditional into the wrapper element and move the <slot></slot> element around:

render() {
    return this.somedCondition ? html`<div><slot></slot></slot>` : html`<slot></slot>`;
}

I don't like this solution since it introduces a lot of "useless" wrapper components. How can I reuse the partial DOM?

1 Answers

With the new version of litelement, and using unsafe html, the element name can be a variable.

So, you can write

html`<${container}>${expensive}</${container}>`

and set the value of container to "lit-gallery", or "div", depending on the condition

Related