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
Part of #124. This replaces the previous idea of navigation.transition.rollback(), with something that is only scoped to the { commit: "after-transition" } case for now. A future extension to { commit: "immediate" } is gestured at.
Also remove the explainer section for rollback, since we've had fewer requests for it. We can keep #124 open to discuss it though.
- [Performance timeline API integration](#performance-timeline-api-integration)
103
-
- [Navigation transition rollbacks and redirects](#navigation-transition-rollbacks-and-redirects)
104
104
- [More](#more)
105
105
- [Stakeholder feedback](#stakeholder-feedback)
106
106
- [Acknowledgments](#acknowledgments)
@@ -704,9 +704,29 @@ If a handler passed to `intercept()` rejects before `e.commit()` is called, then
704
704
705
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.
706
706
707
+
#### Redirects during deferred commit
708
+
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:
710
+
711
+
```js
712
+
navigation.addEventListener("navigate", e => {
713
+
e.intercept({ async handler() {
714
+
if (await isLoginGuarded(e.destination)) {
715
+
e.redirect("/login");
716
+
}
717
+
718
+
// Render e.destination, keeping in mind e.destination might be updated.
719
+
} });
720
+
});
721
+
```
722
+
723
+
This is simpler than the alternative of canceling the original navigation and starting a newone to the redirect location, because it avoids exposing the intermediate state. For example, only one `navigatesuccess` or `navigateerror`event fires, and if the navigation was triggered by a call to `navigation.navigate()`, the promise only fulfills once the redirect destination is reached.
724
+
725
+
It's possible in the future we could contemplate allowing something similar for `{ commit: "immediate" }` navigations as well. There, we would not be able to hide the intermediate state perfectly, as code would still be able to observe the intermediate `location.href` values and such. But we could treat such post-commit redirects as special types of replace navigations, which "take over" any promises returned from `navigation.navigate()`, delay `navigatesuccess`/`navigateerror` events, etc.
726
+
707
727
### Transitional time after navigation interception
708
728
709
-
Although calling `event.intercept()` to [intercept a navigation](#navigation-monitoring-and-interception) and convert it into a single-page navigation immediately and synchronously updates `location.href`, `navigation.currentEntry`, and the URL bar, the handlers passed to `intercept()` can return promises that might not settle for a while. Duringthis transitional time, before the promise settles and the `navigatesuccess` or `navigateerror` events fire, an additional API is available, `navigation.transition`. It has the following properties:
729
+
As part of calling `event.intercept()` to [intercept a navigation](#navigation-monitoring-and-interception) and convert it into a single-page navigation, the handlers passed to `intercept()` can return promises that might not settle for a while. During this transitional time, before the promise settles and the `navigatesuccess` or `navigateerror` events fire, an additional API is available, `navigation.transition`. It has the following properties:
710
730
711
731
- `navigationType`: either `"reload"`, `"push"`, `"replace"`, or `"traverse"` indicating what type of navigation this is
712
732
- `from`: the `NavigationHistoryEntry` that was the current one before the transition
During the [transitional time after navigation interception](#transitional-time-after-navigation-interception), there are several higher-level operations that we believe would be useful for developers:
1390
-
1391
-
- `navigation.transition.rollback()`: a method which allows easy rollback to the `navigation.transition.from` entry.
1392
-
- `navigation.transition.redirect()`: a method which allows changing the destination of the current transition to a new URL.
1393
-
1394
-
Note that `navigation.transition.rollback()` is not the same as `navigation.back()`: for example, if the user navigates two steps back, then `navigation.rollback()` will actually go forward two steps. Similarly, it handles rolling back replace navigations by reverting back to the previous URL and navigation API state. And it rolls back push navigations by actually removing the entry that was previously pushed, instead of leaving it there for the user to reach by pressing their forward button.
1395
-
1396
-
Here is an example of how you could use `navigation.transition.rollback()` to give a different sort of experience for [handling failed navigations](#example-handling-failed-navigations):
1397
-
1398
-
```js
1399
-
navigation.addEventListener("navigateerror", async e => {
1400
-
const attemptedURL = location.href;
1401
-
1402
-
await navigation.transition.rollback().committed;
1403
-
showErrorToast(`Could not load ${attemptedURL}: ${e.message}`);
1404
-
});
1405
-
```
1406
-
1407
-
And here is an example of how you could use `navigation.transition.redirect()` to implement a "redirect" to a login page:
In more detail, such a "redirect" would consist of either doing a replacement navigation (if we're past navigation commit time), or canceling the current not-yet-committed navigation and starting a new one. In both cases, the main value add is to avoid extra intermediate events such as `navigateerror` or `navigatesuccess`; it would seem to the rest of the code as if the navigation just took longer to finish.
1423
-
1424
1407
### More
1425
1408
1426
1409
Check out the [addition](https://github.com/WICG/navigation-api/issues?q=is%3Aissue+is%3Aopen+label%3Aaddition) label on our issue tracker to see more proposals we've thought about!
0 commit comments