Blazor WebAssembly App - Warn user on navigation - 在离开带有未保存更改的网页之前警告用户
Blazor WebAssembly App - Warn user on navigation - warn user before leaving web page with unsaved changes
我在 wwwroot
- index.html
:
中实现了以下代码
"use strict";
(() => {
const modified_inputs = new Set;
const defaultValue = "defaultValue";
// store default values
addEventListener("beforeinput", (evt) => {
const target = evt.target;
if (!(defaultValue in target || defaultValue in target.dataset)) {
target.dataset[defaultValue] = ("" + (target.value || target.textContent)).trim();
}
});
// detect input modifications
addEventListener("input", (evt) => {
const target = evt.target;
let original;
if (defaultValue in target) {
original = target[defaultValue];
} else {
original = target.dataset[defaultValue];
}
if (original !== ("" + (target.value || target.textContent)).trim()) {
if (!modified_inputs.has(target)) {
modified_inputs.add(target);
}
} else if (modified_inputs.has(target)) {
modified_inputs.delete(target);
}
});
// clear modified inputs upon form submission
addEventListener("submit", (evt) => {
modified_inputs.clear();
// to prevent the warning from happening, it is advisable
// that you clear your form controls back to their default
// state with evt.target.reset() or form.reset() after submission
});
// warn before closing if any inputs are modified
addEventListener("beforeunload", (evt) => {
if (modified_inputs.size) {
const unsaved_changes_warning = "Changes you made may not be saved.";
evt.returnValue = unsaved_changes_warning;
return unsaved_changes_warning;
}
});
})();
来源:
如果我尝试在不使用 Blazor 导航的情况下关闭选项卡、重新加载或离开网站,这会非常有效。
我想做的是也能够从这些类型的导航事件中捕获事件:
Navigation.NavigateTo("/");
<NavLink class="nav-link" href="" Match="NavLinkMatch.All">
<span class="oi oi-home" aria-hidden="true"></span> Home
</NavLink>
<MatButtonLink Href="/" Raised="true">Test navigation</MatButtonLink>
我的示例测试代码:
@page "/editor"
@using Markdig;
@inject NavigationManager Navigation
<div class="row">
<div class="col-6">
<textarea class="form-control" @bind-value="Body" @bind-value:event="oninput"></textarea>
<MatButtonLink Href="/" Raised="true">Test navigation</MatButtonLink>
<button @onclick="Navigate">
Test navigation 2
</button>
</div>
<div class="col-6">
@if (!string.IsNullOrWhiteSpace(Body))
{
@((MarkupString)Preview)
}
</div>
</div>
@code {
public string Body { get; set; }
public string Preview => Markdown.ToHtml(Body);
private void Navigate()
{
Navigation.NavigateTo("/");
}
}
找到一个试过的类似问题window.onbeforeunload
:
目前似乎没有解决此问题的方法,但为 .NET 6.0
提交了 NavigationManger 的位置更改事件。我希望可以在应用程序中在全局级别捕获此事件。
总结
从 .NET 5 开始,没有方便的方法使用 Blazor 执行此操作:捕获 click/mouse 事件或使用 JS.
您可以通过 NavigationManager.LocationChanged
订阅这些活动:
[Inject]
NavigationManager Navigation { get; set; }
protected override OnInitialized() {
Navigation.LocationChanged += Handler; // make sure you unsubscribe in a Dispose method
}
private void Handler(LocationChangedEventArgs args) {
// Handle navigation event here
}
请注意,您不能 intercept/prevent 这些导航事件 (当前):您需要拦截 click/mouse 事件而不是在 c# 中实现它。这并不理想,但您需要执行以下操作:
<NavLink class="nav-link"
href=""
Match="NavLinkMatch.All"
@onclick:preventDefault="shouldPreventDefault">
<span class="oi oi-home" aria-hidden="true"></span> Home
</NavLink>
其中 shouldPreventDefault
是布尔值,可能由某些作用域状态或服务提供。
在JS中,可能很简单,就是监听点击事件,例如:
document.addEventListener('click', (e) => {
// shouldPreventDefault set when this behavior is desirable,
// e.g. when changes are unsaved.
if (shouldPreventDefault && e.target instanceof HTMLAnchorElement) {
e.preventDefault();
// etc....
}
}
我在 wwwroot
- index.html
:
"use strict";
(() => {
const modified_inputs = new Set;
const defaultValue = "defaultValue";
// store default values
addEventListener("beforeinput", (evt) => {
const target = evt.target;
if (!(defaultValue in target || defaultValue in target.dataset)) {
target.dataset[defaultValue] = ("" + (target.value || target.textContent)).trim();
}
});
// detect input modifications
addEventListener("input", (evt) => {
const target = evt.target;
let original;
if (defaultValue in target) {
original = target[defaultValue];
} else {
original = target.dataset[defaultValue];
}
if (original !== ("" + (target.value || target.textContent)).trim()) {
if (!modified_inputs.has(target)) {
modified_inputs.add(target);
}
} else if (modified_inputs.has(target)) {
modified_inputs.delete(target);
}
});
// clear modified inputs upon form submission
addEventListener("submit", (evt) => {
modified_inputs.clear();
// to prevent the warning from happening, it is advisable
// that you clear your form controls back to their default
// state with evt.target.reset() or form.reset() after submission
});
// warn before closing if any inputs are modified
addEventListener("beforeunload", (evt) => {
if (modified_inputs.size) {
const unsaved_changes_warning = "Changes you made may not be saved.";
evt.returnValue = unsaved_changes_warning;
return unsaved_changes_warning;
}
});
})();
来源:
如果我尝试在不使用 Blazor 导航的情况下关闭选项卡、重新加载或离开网站,这会非常有效。
我想做的是也能够从这些类型的导航事件中捕获事件:
Navigation.NavigateTo("/");
<NavLink class="nav-link" href="" Match="NavLinkMatch.All">
<span class="oi oi-home" aria-hidden="true"></span> Home
</NavLink>
<MatButtonLink Href="/" Raised="true">Test navigation</MatButtonLink>
我的示例测试代码:
@page "/editor"
@using Markdig;
@inject NavigationManager Navigation
<div class="row">
<div class="col-6">
<textarea class="form-control" @bind-value="Body" @bind-value:event="oninput"></textarea>
<MatButtonLink Href="/" Raised="true">Test navigation</MatButtonLink>
<button @onclick="Navigate">
Test navigation 2
</button>
</div>
<div class="col-6">
@if (!string.IsNullOrWhiteSpace(Body))
{
@((MarkupString)Preview)
}
</div>
</div>
@code {
public string Body { get; set; }
public string Preview => Markdown.ToHtml(Body);
private void Navigate()
{
Navigation.NavigateTo("/");
}
}
找到一个试过的类似问题window.onbeforeunload
:
目前似乎没有解决此问题的方法,但为 .NET 6.0
提交了 NavigationManger 的位置更改事件。我希望可以在应用程序中在全局级别捕获此事件。
总结
从 .NET 5 开始,没有方便的方法使用 Blazor 执行此操作:捕获 click/mouse 事件或使用 JS.
您可以通过 NavigationManager.LocationChanged
订阅这些活动:
[Inject]
NavigationManager Navigation { get; set; }
protected override OnInitialized() {
Navigation.LocationChanged += Handler; // make sure you unsubscribe in a Dispose method
}
private void Handler(LocationChangedEventArgs args) {
// Handle navigation event here
}
请注意,您不能 intercept/prevent 这些导航事件 (当前):您需要拦截 click/mouse 事件而不是在 c# 中实现它。这并不理想,但您需要执行以下操作:
<NavLink class="nav-link"
href=""
Match="NavLinkMatch.All"
@onclick:preventDefault="shouldPreventDefault">
<span class="oi oi-home" aria-hidden="true"></span> Home
</NavLink>
其中 shouldPreventDefault
是布尔值,可能由某些作用域状态或服务提供。
在JS中,可能很简单,就是监听点击事件,例如:
document.addEventListener('click', (e) => {
// shouldPreventDefault set when this behavior is desirable,
// e.g. when changes are unsaved.
if (shouldPreventDefault && e.target instanceof HTMLAnchorElement) {
e.preventDefault();
// etc....
}
}