-
Notifications
You must be signed in to change notification settings - Fork 10.4k
[Blazor] Allow enhanced navigation when an interactive router is present #50012
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,7 +21,8 @@ let resolveCurrentNavigation: ((shouldContinueNavigation: boolean) => void) | nu | |
// These are the functions we're making available for invocation from .NET | ||
export const internalFunctions = { | ||
listenForNavigationEvents, | ||
enableNavigationInterception: setHasInteractiveRouter, | ||
enableNavigationInterception, | ||
disableNavigationInterception, | ||
setHasLocationChangingListeners, | ||
endLocationChanging, | ||
navigateTo: navigateToFromDotNet, | ||
|
@@ -46,6 +47,20 @@ function listenForNavigationEvents( | |
currentHistoryIndex = history.state?._index ?? 0; | ||
} | ||
|
||
async function enableNavigationInterception(uriInDotNet?: string) { | ||
setHasInteractiveRouter(true); | ||
if (uriInDotNet && location.href !== uriInDotNet) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In what scenarios does this happen? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here's an example:
|
||
// The location known by .NET is out of sync with the actual browser location. | ||
// Therefore, we should notify .NET that the location has changed so that any | ||
// interactive router can react accordingly. | ||
await notifyLocationChanged(false); | ||
} | ||
} | ||
|
||
function disableNavigationInterception() { | ||
setHasInteractiveRouter(false); | ||
} | ||
|
||
function setHasLocationChangingListeners(hasListeners: boolean) { | ||
hasLocationChangingEventListeners = hasListeners; | ||
} | ||
|
@@ -101,7 +116,7 @@ export function navigateTo(uri: string, forceLoadOrOptions: NavigationOptions | | |
// Normalize the parameters to the newer overload (i.e., using NavigationOptions) | ||
const options: NavigationOptions = forceLoadOrOptions instanceof Object | ||
? forceLoadOrOptions | ||
: { forceLoad: forceLoadOrOptions, replaceHistoryEntry: replaceIfUsingOldOverload }; | ||
: { forceLoad: forceLoadOrOptions, preferEnhancedNavigation: false, replaceHistoryEntry: replaceIfUsingOldOverload }; | ||
|
||
navigateToCore(uri, options); | ||
} | ||
|
@@ -115,7 +130,9 @@ function navigateToFromDotNet(uri: string, options: NavigationOptions): void { | |
function navigateToCore(uri: string, options: NavigationOptions, skipLocationChangingCallback = false): void { | ||
const absoluteUri = toAbsoluteUri(uri); | ||
|
||
if (!options.forceLoad && isWithinBaseUriSpace(absoluteUri)) { | ||
if (options.preferEnhancedNavigation && hasProgrammaticEnhancedNavigationHandler() && isWithinBaseUriSpace(absoluteUri)) { | ||
performProgrammaticEnhancedNavigation(absoluteUri, options.replaceHistoryEntry); | ||
} else if (!options.forceLoad && isWithinBaseUriSpace(absoluteUri)) { | ||
if (shouldUseClientSideRouting()) { | ||
performInternalNavigation(absoluteUri, false, options.replaceHistoryEntry, options.historyEntryState, skipLocationChangingCallback); | ||
} else { | ||
|
@@ -273,6 +290,7 @@ function shouldUseClientSideRouting() { | |
// Keep in sync with Components/src/NavigationOptions.cs | ||
export interface NavigationOptions { | ||
forceLoad: boolean; | ||
preferEnhancedNavigation: boolean; | ||
replaceHistoryEntry: boolean; | ||
historyEntryState?: string; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
@page "/routing/interactive" | ||
@using TestContentPackage | ||
|
||
<nav> | ||
<NavLink href="routing/interactive">Home</NavLink> | ||
<NavLink href="routing/interactive/navigation">Navigation</NavLink> | ||
</nav> | ||
<hr/> | ||
|
||
<InteractiveRouter @rendermode="@(new ServerRenderMode(false))" /> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
@page "/routing/interactive/{pageName}" | ||
|
||
<h1>Fallback page for <span id="page-name">@PageName</span>!</h1> | ||
|
||
@code { | ||
[Parameter] | ||
public string PageName { get; set; } | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
@using Microsoft.AspNetCore.Components.Routing | ||
|
||
<Router AppAssembly="@typeof(InteractiveRouter).Assembly"> | ||
<Found Context="routeData"> | ||
<RouteView RouteData="@routeData" /> | ||
</Found> | ||
<NotFound>Not found using interactive router</NotFound> | ||
</Router> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
@page "/routing/interactive" | ||
|
||
<h1>Hello from index!</h1> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
@page "/routing/interactive/navigation" | ||
@inject NavigationManager Navigation | ||
|
||
<h3>Hello from navigation page!</h3> | ||
|
||
<button id="normal-refresh" @onclick="NormalRefresh">Normal refresh</button> | ||
<button id="enhanced-refresh" @onclick="EnhancedRefresh">Enhanced refresh</button> | ||
<button id="enhanced-refresh-fallback" @onclick="EnhancedRefreshWithFallback">Enhanced refresh with fallback</button> | ||
|
||
@code { | ||
private void NormalRefresh() | ||
{ | ||
Navigation.NavigateTo(Navigation.Uri, new NavigationOptions() | ||
{ | ||
ReplaceHistoryEntry = true, | ||
}); | ||
} | ||
|
||
private void EnhancedRefresh() | ||
{ | ||
Navigation.NavigateTo(Navigation.Uri, new NavigationOptions() | ||
{ | ||
ReplaceHistoryEntry = true, | ||
PreferEnhancedNavigation = true, | ||
}); | ||
} | ||
|
||
private void EnhancedRefreshWithFallback() | ||
{ | ||
Navigation.NavigateTo(Navigation.Uri, new NavigationOptions() | ||
{ | ||
ReplaceHistoryEntry = true, | ||
PreferEnhancedNavigation = true, | ||
ForceLoad = true, | ||
}); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it OK for us to consume this exception?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep. This happens if the browser is no longer available, in which case there's no browser-side state to clean up. In other words, if this exception gets thrown, it means there's no work to do.