New to Telerik UI for Blazor? Start a free 30-day trial
How to Prompt Users for Unsaved Changes on Navigation
Environment
Product | Form for Blazor |
Description
This knowledge base article answers the following questions:
- How to detect unsaved changes in a Blazor TelerikForm?
- How to prompt users before navigating away from unsaved changes in Form?
- How to conditionally navigate away from a form?
Solution
To prompt the users with a warning message when they attempt to navigate away from a page with unsaved changes in a TelerikForm, follow these steps:
- Inject
NavigationManager
to handle navigation - Register a handler using
NavigationManager.RegisterLocationChangingHandler()
to intercept navigation attempts - Use the
LocationChangingHandler
to check if the form has unsaved changes - Add a
<TelerikDialog>
to prompt the user when there are unsaved changes - Implement a
PreventLeaving()
method andProceedNavigation()
method to close the dialog without navigating and to manually navigate to the stored URL if the user confirms
@implements IDisposable
@inject NavigationManager NavigationManager
<TelerikForm @ref="@FormRef"
Model="@Employee"
Width="300px">
<FormItems>
<FormItem Field="@nameof(Person.Id)" Enabled="false"></FormItem>
<FormAutoGeneratedItems />
</FormItems>
</TelerikForm>
<TelerikButton OnClick="@(() => NavigateToExternalPage())">
Go To Other Page
</TelerikButton>
<TelerikDialog @bind-Visible="@ShowNavigationDialog"
Title="Confirm Navigation">
<DialogContent>
You have unsaved changes. Are you sure you want to leave this page?
</DialogContent>
<DialogButtons>
<TelerikButton OnClick="@PreventLeaving">No</TelerikButton>
<TelerikButton ThemeColor="@ThemeConstants.Button.ThemeColor.Primary" OnClick="@ProceedNavigation">Yes</TelerikButton>
</DialogButtons>
</TelerikDialog>
@code {
private Person Employee = new Person();
private TelerikForm? FormRef { get; set; }
private IDisposable? NavEventRegistration;
private bool ShowNavigationDialog = false;
private string? NextUrl;
private bool isNavigationConfirmed = false; // Flag to track navigation confirmation
private ValueTask LocationChangingHandler(LocationChangingContext args)
{
// Prevent the confirmation dialog from appearing again once the user confirmed navigation
if (isNavigationConfirmed)
{
return ValueTask.CompletedTask;
}
if (FormRef?.EditContext.IsModified() ?? false)
{
// Prevent navigation and store the target URL
args.PreventNavigation();
NextUrl = args.TargetLocation;
ShowNavigationDialog = true;
// Force Blazor to re-render
InvokeAsync(StateHasChanged);
}
return ValueTask.CompletedTask;
}
private void NavigateToExternalPage()
{
NavigationManager.NavigateTo("https://www.telerik.com/blazor-ui/documentation/introduction", forceLoad: true);
}
private void PreventLeaving()
{
// Simply close the dialog without changing the page
ShowNavigationDialog = false;
StateHasChanged();
}
private void ProceedNavigation()
{
// Set the flag to indicate navigation is confirmed
isNavigationConfirmed = true;
// Navigate manually to the stored target URL
if (!string.IsNullOrEmpty(NextUrl))
{
NavigationManager.NavigateTo(NextUrl);
}
// Close the dialog after confirming navigation
ShowNavigationDialog = false;
}
protected override void OnInitialized()
{
Employee = new Person()
{
Id = 1,
FirstName = "John",
LastName = "Doe",
BirthDate = DateTime.Today.AddYears(-30)
};
// Register the navigation handler
NavEventRegistration = NavigationManager.RegisterLocationChangingHandler(LocationChangingHandler);
}
public void Dispose()
{
NavEventRegistration?.Dispose();
}
public class Person
{
public int Id { get; set; }
public string FirstName { get; set; } = string.Empty;
public string LastName { get; set; } = string.Empty;
public DateTime BirthDate { get; set; } = DateTime.Today;
}
}