Reputation: 61
I'm working on a Blazor Server-Side application. The NavBar on the left as anyone familiar with Blazor is populated with hyperlinks, just decorated with a special css class. My problem is, I'm trying to stop navigation and show a pop-up on one specific page if anything has been edited.
I've tried using a handler from LocationChanged to catch it, but it doesn't fire the method off until after the url is already changed. I've tried using dbContext.ChangeTracker.HasChanges() in an if statement and then had a modal pop-up that asked if you wanted to save changes or navigate away, but I can't find a way to fire it off BEFORE the url changed. I've tried a nuget package called BlazorBeforeUnload to add an event handler that catches the redirect or routing before it happens, but it's written for .net standard 2.0, not .net core 3.0. I can write C# decently, but I'm not good enough to figure out how to convert it from one to the other, or to know if it's even possible in this case.
I expected to have some method of firing an event right before the page re-routes or refreshes, but I can't seem to find anything either in Visual Studio or elsewhere online aside from the .net standard 2.0 package that gives me build errors.
Upvotes: 6
Views: 3741
Reputation: 642
If you are using .NET 7 they have finally added an event for this making it very easy. My sample code below is in my ".cs" code-behind file not my ".razor" file (so that you understand the syntax). Also it's from a client-side Blazor WASM project, but I think something similar should be possible server-side.
First, inject the NavigationManager:
[Inject] public NavigationManager navigationManager { get; set; }
Then register your handler from somewhere (in my case from one of my lifecycle event handlers):
navigationManager.RegisterLocationChangingHandler(LocationChangingHandler);
My event handler method looks like this:
private ValueTask LocationChangingHandler(LocationChangingContext arg) {
Console.WriteLine($"AUTH: NAV: About to navigate to {arg.TargetLocation} by {Environment.StackTrace}");
return ValueTask.CompletedTask;
}
Upvotes: 2
Reputation: 163
I think this answer might be revelant.. You may get more about such stuff here: https://wellsb.com/csharp/aspnet/blazor-singleton-pass-data-between-pages/
AppData.cs:
namespace AppDataService.Services
{
public class AppData
{
public string dangerfield { get; set; }
}
}
Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddSingleton<WeatherForecastService>();
services.AddScoped<...>();//singleton if'd be client-side
} ↑
your class here
NavMenu.razor:
<div class="top-row pl-4 navbar navbar-dark">
<a class="navbar-brand" href="">TodoInBlazor</a>
<button class="navbar-toggler" @onclick="ToggleNavMenu">
<span class="navbar-toggler-icon"></span>
</button>
</div>
@inject NavigationManager NavigationManager
@inject Services.AppData AppData
<div class="@NavMenuCssClass" @onclick="ToggleNavMenu">
<ul class="nav flex-column">
<li class="nav-item px-3">
<NavLink class="nav-link" @onclick="Navigate" Match="NavLinkMatch.All">
<span class="oi oi-home" aria-hidden="true"></span> Home
</NavLink>
</li>
<li class="nav-item px-3">
<NavLink class="nav-link" @onclick="Navigate1">
<span class="oi oi-plus" aria-hidden="true"></span> Counter
</NavLink>
</li>
<li class="nav-item px-3">
<NavLink class="nav-link" @onclick="Navigate2">
<span class="oi oi-list-rich" aria-hidden="true"></span> Fetch data
</NavLink>
</li>
</ul>
</div>
@code {
private bool collapseNavMenu = true;
private string NavMenuCssClass => collapseNavMenu ? "collapse" : null;
private void ToggleNavMenu()
{
collapseNavMenu = !collapseNavMenu;
}
private void Navigate()
{
// ↓ Example
if(AppData.dangerfield != null)
NavigationManager.NavigateTo("");
}
private void Navigate1()
{
NavigationManager.NavigateTo("counter");
}
private void Navigate2()
{
NavigationManager.NavigateTo("fetchdata");
}
}
Index.razor:
@inject Services.AppData AppData
<textarea @bind="AppData.dangerfield"></textarea>
Please, vote, I've been working a lot on this..
Upvotes: 3