如何解决Angular CanDeactivate Guard 无法与 MatDialog 正常工作
我已经创建了一个带有 CanDeactivate 的路由守卫,它确定用户是否可以在有任何未保存的更改时离开页面,并在存在任何未保存的更改时触发 MatDialog 模式。我查看了大量指南和类似的线程,并且我的代码正在运行(在大多数情况下)。见下文:
这里是路由守卫,它调用组件的confirmRouteChange函数,如果有,并返回结果,一个Observable<boolean>
:
@Injectable({
providedIn: 'root'
})
export class UnsavedChangesGuard implements CanDeactivate<DirtyComponent> {
canDeactivate(component: DirtyComponent): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
return component?.confirmRouteChange ? component.confirmRouteChange() : true;
}
}
这里是confirmRouteChange的实现,它只是在表单脏时打开MatDialog并返回Observable,当对话框关闭时通知:
confirmRouteChange() {
if (this.isDirty) {
let dialogRef = this.matDialog.open(AlertModalComponent,{
data: {
msg: 'Your changes have not been saved. If you leave this page,your changes will be lost.',title: 'Changes have not been saved',class: 'save-changes'
}
});
return dialogRef.afterClosed();
} else {
return true;
}
}
这是我的模态保存/关闭选项的实现:
save() {
this.dialogRef.close(false);
}
close() {
this.dialogRef.close(true);
}
所以这是我的问题:当我用未保存的更改导航离开时,模态弹出(很棒),应用程序根据模态中选择的选项正确导航(很棒);但是,在模态后面,我可以看到我的应用程序的其余部分导航离开页面,除了放置路由保护的组件的页面。因此,如果我尝试导航到主页,我可以看到所有主页和具有未保存更改形式的组件。就好像它开始导航,停止,然后等待用户的响应。如果我使用本机 confirm()
对话框,它可以完美运行,这意味着应用程序在等待用户响应时有效地冻结。我相信这是因为如果我记录 confirm()
返回的内容,在用户选择某些内容之前它不会返回任何内容。另一方面,dialogRef.afterClosed()
立即返回 Observable,我猜这会触发导航,然后应用停止并等待用户的响应。
我认为我对模态的使用有问题,但我不确定是什么。非常感谢任何帮助!
编辑:我认为 return dialogRef.afterClosed()
语句在对话框完成打开之前执行,导致导航开始然后停止。
解决方法
这正是你描述的方式。
您的路由守卫期望立即为真或假。它无法处理可观察对象。
所以我的建议是执行以下操作。
第一
检查一下,但是当组件脏时直接返回 false,以便路由保护防止重新路由。构建一个服务,该服务存储新路由并包含一个名为 reroutingAllowed
的字段。最初设置为 false
。
canDeactivate(component: DirtyComponent): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
return component?.isDirty();
}
confirmRouteChange() {
// here we already take the new field into account
if (this.isDirty && !reroutingAllowed) {
let dialogRef = this.matDialog.open(AlertModalComponent,{
data: {
msg: 'Your changes have not been saved. If you leave this page,your changes will be lost.',title: 'Changes have not been saved',class: 'save-changes'
}
});
// directly return false
return false;
} else {
return true;
}
}
第二
在您的服务中并行记住用户想要前往的新路线目标,以便在用户在模态对话框中满足其决定时访问它。
第三
等待用户回答对话框。如果他想离开当前页面,将变量 reroutingAllowed
设置为 true
并触发 Angular 路由器再次调用新的路由目标。
这次守卫会让用户通过,尽管表单仍然很脏。
您只需要考虑如何设置上述服务以及如何获取和记住新的路由目标。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。