Using Turbo Frames in LitElement

63 Views Asked by At

I have a web application using Turbo Frames from Hotwire. The basic layout looks like this:

<nav>
    <nav-button path="/desktop" label="Desktop"></nav-button>
    <nav-button path="/about" label="About"></nav-button>
</nav>
<div>
    <turbo-frame id="body" data-turbo-action="advance">
    </turbo-frame>
</div>

And my NavButton is the following:

import {html, LitElement} from "lit";

export class NavButton extends LitElement {
    static get properties() {
        return {
            path: {type: String},
            label: {type: String},
        }
    }

    render() {
        return html`
            <a href="${this.path}" data-turbo-frame="body">
                ${this.label}
            </a>
        `;
    }

    connectedCallback() {
        super.connectedCallback();
        window.addEventListener('turbo:visit', this.handleVisit);
    }

    disconnectedCallback() {
        window.removeEventListener('turbo:visit', this.handleVisit);
        super.disconnectedCallback();
    }

    handleVisit = (event) => {
        const anchorElement = this.shadowRoot.querySelector('a');

        if (event.detail.url.endsWith(this.path)) {
            anchorElement.style.fontWeight = 'bold';
        } else {
            anchorElement.style.fontWeight = 'normal';
        }
    }
}

customElements.define('nav-button', NavButton);

When I use the anchor elements directly instead of the nav-button elements in my html everything works fine. It also works when I use the nav-button elements and turn off the Shadow Dom in my LitElement with:

createRenderRoot() {
    return this;
}

But when using the LitElement with Shadow Dom it's not only the frame which gets rerendered, the whole page gets rerendered. Is it event possible to work like this? Or can I not use the data-turbo-frame attribute inside a LitElement at all?

For better clarity: Those web components are not meant to be used in different projects, so the answer might be "just use React/Vue/Svelte etc." But nonetheless I like the idea of using web components which can be used with any other JS library.

Are there alternatives? Maybe someone can help me out as I am still new to web components.

0

There are 0 best solutions below