tracks form changes and warns users before navigation
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
@namespace WebApp.Components.Shared.Components
|
||||
@implements IDisposable
|
||||
@inject IDialogService DialogService
|
||||
@inject NavigationManager NavigationManager
|
||||
|
||||
@code {
|
||||
[CascadingParameter]
|
||||
private EditContext? EditContext { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public EditContext? ExplicitEditContext { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public bool Enabled { get; set; } = true;
|
||||
|
||||
private bool _isDirty = false;
|
||||
private bool _allowNavigation = false;
|
||||
private IDisposable? _navigationRegistration;
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
var contextToUse = ExplicitEditContext ?? EditContext;
|
||||
|
||||
if (contextToUse == null)
|
||||
{
|
||||
throw new InvalidOperationException("FormChangeTracker requires an EditContext. Either provide it as a cascading parameter or through the ExplicitEditContext parameter.");
|
||||
}
|
||||
|
||||
// Subscribe to field changes to detect when form becomes dirty
|
||||
contextToUse.OnFieldChanged += HandleFieldChanged;
|
||||
|
||||
// Register navigation handler to intercept navigation attempts
|
||||
_navigationRegistration = NavigationManager.RegisterLocationChangingHandler(OnLocationChanging);
|
||||
}
|
||||
|
||||
private void HandleFieldChanged(object? sender, FieldChangedEventArgs e)
|
||||
{
|
||||
if (Enabled)
|
||||
{
|
||||
_isDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
private async ValueTask OnLocationChanging(LocationChangingContext context)
|
||||
{
|
||||
// Allow navigation if form isn't dirty, navigation is explicitly allowed, or tracking is disabled
|
||||
if (!_isDirty || _allowNavigation || !Enabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Show confirmation dialog
|
||||
var result = await DialogService.ShowMessageBox(
|
||||
"Unsaved Changes",
|
||||
"You have unsaved changes. Are you sure you want to leave this page?",
|
||||
yesText: "Leave",
|
||||
cancelText: "Stay");
|
||||
|
||||
// If user chooses to stay (result is null or false), prevent navigation
|
||||
if (result != true)
|
||||
{
|
||||
context.PreventNavigation();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Call this method before programmatic navigation to bypass the unsaved changes warning.
|
||||
/// Use this when the form has been successfully saved or when the user explicitly cancels.
|
||||
/// </summary>
|
||||
public void AllowNavigation()
|
||||
{
|
||||
_allowNavigation = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reset the dirty state of the form. This marks the form as clean and resets the navigation flag.
|
||||
/// </summary>
|
||||
public void MarkClean()
|
||||
{
|
||||
_isDirty = false;
|
||||
_allowNavigation = false;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
var contextToUse = ExplicitEditContext ?? EditContext;
|
||||
if (contextToUse != null)
|
||||
{
|
||||
contextToUse.OnFieldChanged -= HandleFieldChanged;
|
||||
}
|
||||
_navigationRegistration?.Dispose();
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
@namespace WebApp.Components.Shared.Components
|
||||
@using MudBlazor
|
||||
|
||||
<PageTitle>@GetPageTitle()</PageTitle>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user