Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: Retrieve the element (if any) triggering the navigation #238

Closed
VicGUTT opened this issue Jun 14, 2022 · 2 comments
Closed

feature: Retrieve the element (if any) triggering the navigation #238

VicGUTT opened this issue Jun 14, 2022 · 2 comments

Comments

@VicGUTT
Copy link

VicGUTT commented Jun 14, 2022

Retrieve the element (if any) triggering the navigation

Playing around with the Navigation API, there doesn't seem to be, as of now, a way to retrieve the element triggering the navigation.

The NavigateEvent event provides us a userInitiated property which allows us to determine if the navigation was triggered by a user action (click, form submit, ...) or programatically (navigation.navigate(), el.click(), ...). But we lack a way to determine what triggered the navigation.

Background/Motivation

My interest comes from creating SPA-like feeling MPAs. Meaning, traditional server driven apps, where every request returns a fully or partially formed HTML document (instead of JSON). The SPA-like feeling would come from making XHR/fetch requests once a navigation/resource is requested (via a clicked link or form submission) and on response, swap out the old document for the new one, or morph the new content into the old one (using a library like morphdom).

Use cases

Consider a visit library that you'd install from NPM to SPA-ify your app.

You could use it to make visits, aka navigations in one of two ways:

Directly from your JS

import visit from 'visit';

visit.get('/about'); // <- a glorified `navigation.navigate()`
visit.put('/post/3', { headers: {...}, body: new FromData(el) ); // <- `navigation.navigate()` + configure the underlying fetch request
visit({ url: '/post/3', method: 'DELETE', headers: {...}, ... })

Directly from your HTML

<a href="/about" data-visit>About page</a>

<form action="/post/3" data-visit data-visit-method="PUT" data-visit-headers="{...}">
    ...
</form>

<button data-visit="{ url: '/post/3', method: 'DELETE', headers: {...}, ... }">
    ...
</button>

And the underlying library code could be roughly similar to:

function visit(params) {
    // ...

    navigation.addEventListener('navigate', (e) => {
        const element = e.targetElement; // <- Element or null

        if (!element || !element.hasAttribute('data-visit')) {
            return;
        }

        e.transitionWhile(
            fetch({
                url: element.getAttribute('data-visit-url') || determineUrlToUseFromElement(element),
                method: element.getAttribute('data-visit-method') || determineMethodToUseFromElement(element),
                // ...
            })
            .then(response => response.text())
            .then(html => swapDom(html))
        );
    });
}

Without having a targetElement (or whatever the name would be) property on the event, the declarative feature of customizing the request throught HTML attributes would only be possible by attaching an event to every elements individually, which would negate the "centralized router" of the API.

@domenic
Copy link
Collaborator

domenic commented Jun 14, 2022

Dupe of #225?

@domenic domenic closed this as completed Jun 14, 2022
@VicGUTT
Copy link
Author

VicGUTT commented Jun 14, 2022

Wow yes, sorry about that. Couldn't find any similar issues for some reason.
Will continue the conversation over there ✌️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants