Signatur
Beschreibung
Das Ereignis navigatesuccess gehört zur Navigation API und wird am Navigation-Objekt (window.navigation) ausgelöst, wenn eine Navigation erfolgreich beendet ist. Bei Navigationen, die im navigate-Ereignis per event.intercept({ handler }) abgefangen wurden, passiert das erst, wenn alle von den Handlern zurückgegebenen Promises erfüllt sind. Ohne Handler (etwa bei reinen Fragment-Navigationen) feuert das Ereignis direkt nach dem Commit.
Typische Einsatzzwecke in Single-Page-Anwendungen: Ladeanzeigen ausblenden, Fokus setzen und Screenreadern den Seitenwechsel ankündigen, Analytics-Seitenaufrufe erfassen oder Scrollpositionen wiederherstellen – also alles, was erst sinnvoll ist, wenn der neue Inhalt wirklich gerendert ist.
Das Ereignisobjekt ist ein einfaches Event ohne zusätzliche Eigenschaften. Informationen zur abgeschlossenen Navigation liest man über navigation.currentEntry (z. B. url, key, getState()) aus. Das Gegenstück bei Fehlschlag oder Abbruch ist navigateerror. Registrieren lässt sich der Listener per addEventListener("navigatesuccess", …) oder über die Eigenschaft navigation.onnavigatesuccess.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $type Pflicht | string | Der Ereignisname "navigatesuccess". |
|
| $handler Pflicht | (event: Event) => void | Callback, der ein generisches Event erhält (nicht abbrechbar, blubbert nicht). |
|
| $options | boolean | AddEventListenerOptions | false | Optionale Listener-Optionen wie once oder signal. |
Rückgabewert
addEventListener gibt nichts zurück. Der Handler erhält ein Event-Objekt.Beispiele
Ladeanzeige nach erfolgreicher SPA-Navigation ausblenden
const spinner = document.querySelector('#spinner');
navigation.addEventListener('navigate', (event) => {
if (!event.canIntercept || event.hashChange) return;
const url = new URL(event.destination.url);
event.intercept({
async handler() {
spinner.hidden = false;
const res = await fetch(`/partials${url.pathname}`);
document.querySelector('main').innerHTML = await res.text();
}
});
});
navigation.addEventListener('navigatesuccess', () => {
spinner.hidden = true;
console.log('Navigation abgeschlossen:', navigation.currentEntry.url);
});
navigation.addEventListener('navigateerror', (event) => {
spinner.hidden = true;
console.error('Navigation fehlgeschlagen:', event.message);
});
Über die on-Property: Seitenaufruf erfassen und Fokus setzen
navigation.onnavigatesuccess = () => {
const heading = document.querySelector('main h1');
if (heading) {
heading.tabIndex = -1;
heading.focus();
}
document.title = heading?.textContent ?? document.title;
console.log('Pageview:', new URL(navigation.currentEntry.url).pathname);
};
// Später entfernen:
// navigation.onnavigatesuccess = null;
Listener gezielt wieder entfernen
const controller = new AbortController();
const onSuccess = () => console.log('Erfolg für', navigation.currentEntry.key);
navigation.addEventListener('navigatesuccess', onSuccess, { signal: controller.signal });
await navigation.navigate('/einstellungen').finished;
// Variante 1: per removeEventListener
navigation.removeEventListener('navigatesuccess', onSuccess);
// Variante 2: per AbortSignal
controller.abort();
Feature-Erkennung mit Fallback
if ('navigation' in window) {
navigation.addEventListener('navigatesuccess', () => {
console.log('Navigation API: fertig');
});
} else {
window.addEventListener('popstate', () => {
console.log('Fallback: History API');
});
}
// Wichtig · Fallstricke
- Browser-Kompatibilität: Die Navigation API gibt es in Chromium-Browsern seit Version 102, in Firefox und Safari erst seit kurzem (2025). Für ältere Browser immer per
'navigation' in windowprüfen und auf History API/popstatezurückfallen. - Das Ereignis feuert erst, wenn alle Promises der
intercept()-Handler erfüllt sind. Wird eine Navigation von einer neuen unterbrochen oder ein Handler wirft einen Fehler, kommt stattdessennavigateerror. Deshalb Aufräumarbeiten (z. B. Spinner) in beiden Ereignissen erledigen. - Pro Navigation lässt sich auch das Promise
navigation.navigate(url).finishedbzw.navigation.transition.finishedverwenden. Das ist oft praktischer als ein globaler Listener. - Das Ereignisobjekt enthält keine URL. Stattdessen
navigation.currentEntryverwenden. - Navigationen zwischen Dokumenten, also komplette Seitenladevorgänge ohne
intercept(), lösen im alten Dokument keinnavigatesuccessaus.