Exit Prompt

Holds a navigation while there is unsaved work, and asks before letting it go. A navigation inside the application gets this component's own dialog; closing the tab or reloading arms the browser's own prompt.

Guarding a Form

The guard is off until you switch it on, because a live prompt on this page would hold your next navigation. Switch it on, then click a sidebar link or the button below to see the dialog. Saving the form, or choosing to leave, clears it again.

Custom Wording

Title, Message, StayLabel and LeaveLabel all fall back to localized defaults. Message is not used for the browser's own prompt, which shows its own wording. Stay renders as ButtonVariant.Outline and Leave as ButtonVariant.Destructive.

Behaviour

Bind Enabled to your own field. The component writes to its own Enabled parameter when the visitor chooses to leave. If you pass a constant or an expression that does not change, the next render restores the old value and re-arms the guard.

The navigation is refused, not held open. The handler calls PreventNavigation(), remembers the target and returns immediately. Holding the router open until a button is pressed moved the URL without rendering the new page, because the reissued navigation was re-entrant within the pipeline still processing the refused one. Refusing first and navigating from the button's own handler keeps the two apart.

Leave clears the guard before reissuing. On Leave the component sets Enabled to false, disarms the browser prompt, raises OnLeft, and only then navigates.

Dismissing the dialog counts as staying. Closing it any way other than the Leave button runs the same path as the Stay button and raises OnStayed. While a navigation is already held, a second one is not intercepted.

Several prompts on a page. Each guards its own work, and the first enabled one prompts. Place one near the form it guards.

It cannot be rendered on the server. OnInitialized calls NavigationManager.RegisterLocationChangingHandler, and the server-side navigation manager used for prerendering and static server rendering does not support a navigation lock. Rendering the component there throws NotSupportedException: To support navigation locks, HttpNavigationManager must override SetNavigationLockState. Place it inside an interactive render mode, or hold it back until the component is interactive. The demo above does the second: it renders only once this page is interactive.

The browser prompt fails quietly. Its JavaScript module is loaded inside a try/catch. If that load fails, in-application navigation is still guarded, because that path never leaves C#. Only the browser-level prompt is lost.