94 lines
2.8 KiB
Plaintext
94 lines
2.8 KiB
Plaintext
@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();
|
|
}
|
|
}
|