This repo contains the code that demonstrates the features of the BlazrRouter
and BlazrNavigationManager
in the Blazor.Routing library. It's principle purpose is to provide functionality to turn routing/navigation on and off. The principle application of this functionality is in edit forms to stop navigation when the form state is dirty.
It's a culmination of many iterations of my own work and code with a contributions from elsewhere including a NavigationManager implementation by Adam Stevenson documented in his Github Repo here. There's a significant amount of Microsoft AspnetCore repository "lifted" code to rebuild the Blazor Router.
The Repo is structured using my Blazor Clean Design Template. It's Net6.0, can be run in either Web Assembly or Server modes - it's the same code base. Just set the appropriate Startup project.
Go to the "Edit Form Demo" page to see the form/page locking concepts in action. Click on the button to toggle the form from dirty to clean and then attempt to navigate away from the page by clicking links, using the back button, F5 or clicking on favourites. There's also some cheeky feedback messages to show the events.
In both Web Assembly and Server all in-browser navigation events are captured by the Blazor JS code. However, they surface very differently in the NetCore libraries.
In Web Assembly the JS navigation event code calls the NotifyLocationChanged
JsInterop registered method. This gets the current instance of WebAssemblyNavigationManager
and calls SetLocation
. Note this gets the instance of WebAssemblyNavigationManager
directly through it's Instance
static method, not through the DI container.
public static class JSInteropMethods
{
[JSInvokable(nameof(NotifyLocationChanged))]
public static void NotifyLocationChanged(string uri, bool isInterceptedLink)
{
WebAssemblyNavigationManager.Instance.SetLocation(uri, isInterceptedLink);
}
}
In Server the calls get transferred over the SignalR connection and are handled by the ComponentHub
public async ValueTask OnLocationChanged(string uri, bool intercepted)
{
var circuitHost = await GetActiveCircuitAsync();
if (circuitHost == null)
return;
_ = circuitHost.OnLocationChangedAsync(uri, intercepted);
}
This calls the CircuitHost
method:
public async Task OnLocationChangedAsync(string uri, bool intercepted)
{
await Renderer.Dispatcher.InvokeAsync(() =>
{
var navigationManager = (RemoteNavigationManager)Services.GetRequiredService<NavigationManager>();
navigationManager.NotifyLocationChanged(uri, intercepted);
});
}
//lots of code missing to only show the relevant lines
This time it gets the registered NavigationManager
service and casts it as a RemoteNavigationManager
object before calling the NotifyLocationChanged
method.
The demo can be run in either Web Assembly or Server modes.
Set Blazr.Demo.Routing.Server.Web as the startup project to run the Server version.
Set Blazr.Demo.Routing.WASM.Web as the startup project to run the Web Assembly version.
-
Add Blazr.Routing to the solution, and add project references where required.
-
Change out the
Router
inApp.razor
@namespace Blazr.UI
<BlazrRouter AppAssembly="@typeof(App).Assembly">
......
</BlazrRouter>
- Add the new Navigation Manager service
services.AddBlazrNavigationManager();
- Add the JS reference to the SPA startup page - __Hosts.html, __Layout.html or index.html .
<script src="_content/Blazr.Routing/site.js"></script>
-
Review
EditForm.razor
for an implementation demo of how to control theBlazrNavigationManager
lock state. -
Add the
PageLocker
component to the page.
@page "/EditForm"
@namespace Blazr.UI
<PageLocker />
//.....