Skip to content

Explore class-based routing solutions #1

@markmals

Description

@markmals

Currently, routes are defined as a JSON array of RouteObject JSON objects. We might be able to simplify this by making each route its own class and mediate metadata we need through decorators. Perhaps something like:

class TasksRoute extends Route {
    static override path = "/"

    // These are the child routes which will appear in this route's
    // <router-outlet> when the URL matches their static `path` property
    static override get children() {
        return [
            new TaskRoute(),
            new NewTaskRoute(),
        ]
    }

    // If we wanted to enable multiple loaders/actions per route
    // we could do something like that with @Loader/@Action
    // decorators, but then we would lose the type inference that
    // comes with overriding named superclass members.
    //
    // I'm also not sure how you would tell the router which of
    // your multiple loaders you wanted to get data from. Maybe 
    // @Loader("name") & this.router.loaderData("name")?
    static override async loader({ request }) {
        return await db.tasks.findAll(request)
    }

    static override async action({ request }) {
        let formData = await request.formData()
        await db.tasks.delete(formData.get("taskId"))
    }

    get tasks() {
        // Can we infer the return type of `loaderData` now that we
        // have the router and loader/action defined on the same class?
        return this.router.loaderData?.tasks ?? []
    }

    get body() {
        return html`
            <h2>Tasks</h2>
            <ul>
                ${ForEach(
                    this.tasks,
                    task => html`
                        <li>
                            <task-item .taskItem=${task}>
                            </task-item>
                        </li>
                    `
                )}
            </ul>
            <a href="/tasks/new" ${this.router.enhanceLink()}>
                Add New Task
            </a>
            <router-outlet></router-outlet>
        `
    }
}

@CustomElement("tasks-app")
class App extends Route {
    static override fallback = html`<p>Loading...</p>`
    static override children = new TasksRoute()
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions