Hemanth's Scribes

web

Navigation API

Author Photo

Hemanth HM

Thumbnail

Navigation API formerly known as the app history API provides an interface for navigations and session history, especially useful for SPAs.

Developers have been complaining that the current navigation and history APIs are fragile, clunky and hard to understand. The navigation API solves this by providing a new interface that is easy for developers to use and understand. Some parts of the platform, e.g. accessibility technology, do not have good visibility into single-page navigations.

This API will enable developers to easily convert cross-document navigations into single-page app same-document ones. It will also provide events for notifying the application about navigations and traversals, which they can use to synchronize application or UI state. In particular, it will allow analytics (first- or third-party) to watch for navigations, including gathering timing information about how long they took.

This API doesn’t allow web applications to intercept user-initiated navigations in a way that would trap the user (e.g., disabling the URL bar or back button). Nor add support for multiple routers on a single page. It doesn’t handle the case where the Android back button is being used as a “close signal”; instead, that’s best handled by a separate API.

The navigation object

navigation is exposed on the global scope with the below attributes:

[
  "currentEntry",
  "transition",
  "canGoBack",
  "canGoForward",
  "onnavigate",
  "onnavigatesuccess",
  "onnavigateerror",
  "oncurrententrychange",
  "back",
  "entries",
  "forward",
  "navigate",
  "reload",
  "traverseTo",
  "updateCurrentEntry",
  "constructor",
]

This contains all the NavigationHistoryEntry which has the below attributes:

[
  'key',
  'id',
  'url',
  'index',
  'sameDocument',
  'ondispose',
  'getState',
  'constructor',
  Symbol(Symbol.toStringTag)
]
  • key → UUID string representing its place in the history list. One can do a navigation.traverseTo(key) to navigate back to this entry.
  • id → Random UUID string representing this specific navigation history entry.
  • url → The URL of this navigation history entry.
  • index → The index of this navigation history entry.
  • sameDocument → Is the current history entry the same Document as the current document value or not is indicated by this key.
  • getState() → Returns deserialized state stored in this entry.

Example

const entry = navigation.entries()[navigation.currentEntry.index];
{
  key: '2f64f187-3671-4f43-844d-c5bea322e159',
  id: 'f2caf453-38a1-4401-b915-83f71eba8d42',
  url: 'https://h3manth.com',
  index: 0,
  sameDocument: true
}
  • event.navigationType → Indicates the navigation type: one of “reload”, “push”, “replace”, or “traverse”
  • event.destination → Represents the destination of the navigation.
  • event.canTransition → true if transitionWhile() can be called to convert this navigation into a single-page navigation; false otherwise.
  • event.userInitiated → true if this navigation was due to a user click, false otherwise.
  • event.hashChange → true if this navigation is a fragment navigation; false otherwise.
  • event.signal → An AbortSignal which will become aborted if the navigation gets canceled.
  • event.formData → The submitted form entries for this navigation, if this navigation is a “push” or “replace” navigation representing a POST form submission; null otherwise.
  • event.downloadRequest → Represents whether or not this navigation was requested to be a download, by using an a or area element’s download attribute.
  • event.info → An arbitrary JavaScript value passed via navigation APIs that initiated this navigation, or null if the navigation was initiated by the user or via a non-navigation API.
event.transitionWhile(newNavigationAction)
event.transitionWhile(newNavigationAction, { focusReset: "manual" })
event.transitionWhile(newNavigationAction, { scrollRestoration: "manual" })

Converts this navigation into a same-document navigation to the destination URL.

Examples from the Spec

SPA Routing

navigation.addEventListener("navigate", e => {
  if (!e.canTransition || e.hashChange || e.downloadRequest !== null) {
    return;
  }

  if (routesTable.has(e.destination.url)) {
    const routeHandler = routesTable.get(e.destination.url);
    e.transitionWhile(routeHandler());
  }
});

### Page-supplied "back"
javascript
backButton.addEventListener("click", () => {
  if (navigation.entries()[navigation.currentEntry.index - 1]?.url === "/cart") {
    navigation.back();
  } else {
    // If the user arrived here by typing the URL directly:
    navigation.navigate("/cart", { history: "replace" });
  }
});

### Navigate and Reload
javascript
// Performs a navigation to the given URL, but replace the current history entry
// instead of pushing a new one.
// (equivalent to `location.replace(url)`)
navigation.navigate(url, { history: "replace" });

// Replace the URL and state at the same time.
navigation.navigate(url, { history: "replace", state });

// You can still pass along info:
navigation.navigate(url, { history: "replace", state, info });
#javascript#web#navigation#spa
Author Photo

About Hemanth HM

Hemanth HM is a Sr. Machine Learning Manager at PayPal, Google Developer Expert, TC39 delegate, FOSS advocate, and community leader with a passion for programming, AI, and open-source contributions.