You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -691,32 +691,38 @@ Some more details on how the navigation API handles scrolling with `"traverse"`
691
691
692
692
- By default, any navigations which are intercepted with `navigateEvent.intercept()` will _ignore_ the value of `history.scrollRestoration` from the classic history API. This allows developers to use `history.scrollRestoration` for controlling cross-document scroll restoration, while using the more-granular option to `intercept()` to control individual same-document navigations.
693
693
694
-
#### Deferred commit
694
+
#### Precommit handlers
695
695
696
-
The default behavior of immediately "committing" (i.e., updating `location.href` and `navigation.currentEntry`) works well for most situations, but some developers may find they do not want to immediately update the URL, and may want to retain the option of aborting the navigation without needing to rollback a URL update or cancel-and-restart. This behavior can be customized using `intercept()`'s `commit` option:
696
+
The default behavior of immediately "committing" (i.e., updating `location.href` and `navigation.currentEntry`) works well for most situations, but some developers may find they do not want to immediately update the URL, and may want to retain the option of aborting the navigation without needing to rollback a URL update or cancel-and-restart. This behavior can be customized passing a `precommitHandler` callback alongside or instead of the `handler` callback:
697
697
698
-
-`e.intercept({ handler, commit: "immediate" })`: the default behavior, immediately commit the navigation and update `location.href` and `navigation.currentEntry`.
699
-
-`e.intercept({ handler, commit: "after-transition" })`: start the navigation (e.g., show a loading spinner if the UI has one), but do not immediately commit.
698
+
- `e.intercept({ handler })`: the default behavior, immediately commit the navigation and update `location.href` and `navigation.currentEntry`.
699
+
- `e.intercept({ precommitHandler })`: start the navigation (e.g., show a loading spinner if the UI has one), but do not immediately commit.
700
700
701
-
When deferred commit is used, the navigation will commit (and a `committed` promise will resolve if present) when `e.commit()` is called. Ifany handler(s) passed to `intercept()` fulfill, and `e.commit()` has not yet been called, we will fallback to committing just before any `finish` promise resolves and `navigatesuccess` is fired.
701
+
The object passed to intercept can include both a `handler` and a `precommitHandler`. If both are included, they are called individually at the appropriate phase.
702
702
703
-
If a handler passed to `intercept()` rejects before `e.commit()` is called, then the navigation will be treated as canceled (both `committed` and `finished` promises will reject, and no URL update will occur). If a handler passed to `intercept()` rejects after `e.commit()`is called, the behavior will match a rejected promise in immediate commit mode (i.e., the `committed` promise will fulfill, the `finished` promise will reject, and the URL will update).
703
+
When precommit handlers are used, the navigation will commit (and a `committed` promise will resolve if present) once all those handlers are fulfilled. Unlike the ordinary `handler`, the `precommitHandler` callbacks are called in sequence—the next `precommit` handler is invoked only when the previous one is fulfilled. That is due to the fact that a precommit handler can asynchronously abort the navigation altogether or redirect the URL, and the next precommit handler should respond to the new state.
704
704
705
-
Because deferred commit can be used to cancel the navigation before the URL updates, it is only available when `e.cancelable` is true. See [above](#restrictions-on-firing-canceling-and-responding) for details on when `e.cancelable` is set to false, and thus deferred commit is not available.
705
+
If a `precommitHandler` passed to `intercept()` rejects, then the navigation will be treated as canceled (both `committed` and `finished` promises will reject, and no URL update will occur).
706
+
707
+
Because precommit handlers can be used to cancel the navigation before the URL updates, they are only available when `e.cancelable` is true. See [above](#restrictions-on-firing-canceling-and-responding) for details on when `e.cancelable` is set to false, and thus precommit handlers are not available. Calling `intercept()` with a `precommitHandler` on a non-cancelable event would throw a `"SecurityError"` `DOMException`.
706
708
707
709
#### Redirects during deferred commit
708
710
709
-
If the `{ commit: "after-transition" }` option is passed to `navigateEvent.intercept()`, then an additional method is available on the `NavigateEvent`:`redirect(url)`. This updates the eventual destination of the `"push"` or `"replace"`navigation. An example usage is as follows:
711
+
The `precommitHandler` callback accepts an argument, which is a `controller` that can perform certain actions on the precommitted navigation, in particular redirecting. This updates the eventual destination of the `"push"` or `"replace"` navigation, and restarts the sequence of calling the precommit handlers. An example usage is as follows
710
712
711
713
```js
712
714
navigation.addEventListener("navigate", e => {
713
-
e.intercept({ async handler() {
714
-
if (await isLoginGuarded(e.destination)) {
715
-
e.redirect("/login");
715
+
e.intercept({
716
+
async precommitHandler(controller) {
717
+
if (await isLoginGuarded(e.destination)) {
718
+
controller.redirect("/login");
719
+
}
716
720
}
717
721
718
-
// Render e.destination, keeping in mind e.destination might be updated.
0 commit comments