Angular 2 CanDeactivate守卫在子组件中不生效问题求助
解决嵌套表单子组件中CanDeactivate守卫不生效的问题
我来帮你排查这个问题!你的核心问题在于:CanDeactivate守卫是和路由绑定的组件(也就是你的UserFormComponent)关联的,它只会检查这个路由组件的状态,不会自动感知到它内部子组件的表单变化。你把表单放在了子组件里,所以守卫自然没法检测到子组件的表单是否有未保存的更改。
下面是具体的解决步骤:
1. 定义统一的激活检查接口
先创建一个接口,让需要做离开确认的组件都实现它:
// 可以放在单独的文件里,比如 can-deactivate.interface.ts export interface CanComponentDeactivate { canDeactivate: () => Observable<boolean> | Promise<boolean> | boolean; }
2. 在子表单组件中实现这个接口
让你的子组件实现上面的接口,在canDeactivate方法里判断表单是否有未保存的更改:
import { Component, ViewChild } from '@angular/core'; import { NgForm } from '@angular/forms'; import { CanComponentDeactivate } from './can-deactivate.interface'; @Component({ selector: 'app-child-form', templateUrl: './child-form.component.html' }) export class ChildFormComponent implements CanComponentDeactivate { @ViewChild('form') form: NgForm; canDeactivate(): boolean | Observable<boolean> { // 检查表单是否被修改过 if (this.form.dirty) { return confirm('你还有未保存的更改,确定要离开当前页面吗?'); } return true; } }
3. 在路由组件中委托检查逻辑到子组件
你的路由组件UserFormComponent需要获取子组件的实例,同样实现CanComponentDeactivate接口,把检查逻辑委托给子组件:
import { Component, ViewChild } from '@angular/core'; import { CanComponentDeactivate } from './can-deactivate.interface'; import { ChildFormComponent } from './child-form/child-form.component'; @Component({ selector: 'app-user-form', templateUrl: './user-form.component.html' }) export class UserFormComponent implements CanComponentDeactivate { // 获取子组件实例 @ViewChild(ChildFormComponent) childFormComponent: ChildFormComponent; canDeactivate(): Observable<boolean> | Promise<boolean> | boolean { // 把检查逻辑交给子组件处理,如果子组件不存在就直接返回true return this.childFormComponent?.canDeactivate() || true; } }
4. 确保守卫服务正确适配接口
检查你的CanDeactivateGuard服务,确保它是针对我们定义的接口进行检查的:
import { Injectable } from '@angular/core'; import { CanDeactivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; import { Observable } from 'rxjs'; import { CanComponentDeactivate } from './can-deactivate.interface'; @Injectable({ providedIn: 'root' }) export class CanDeactivateGuard implements CanDeactivate<CanComponentDeactivate> { canDeactivate( component: CanComponentDeactivate, currentRoute: ActivatedRouteSnapshot, currentState: RouterStateSnapshot, nextState?: RouterStateSnapshot ): Observable<boolean> | Promise<boolean> | boolean { // 调用组件的canDeactivate方法,如果没有实现就返回true return component.canDeactivate ? component.canDeactivate() : true; } }
这样调整之后,当用户尝试离开user/new路由时,守卫会先调用UserFormComponent的canDeactivate方法,进而触发子组件的表单检查逻辑,就能正常弹出确认提示啦!
内容的提问来源于stack exchange,提问作者Siddu hadapad
相关产品推荐
相关产品推荐

