为什么 CanDeactivate Guard 无法读取我组件中的方法?
Why CanDeactivate Guard Can't read a method in my component?
我正在懒惰地加载我的路线。我正在尝试根据文档使用 CanDeactivate
,但守卫似乎无法读取组件的属性或方法。
这是我的守卫,
@Injectable()
export class CanDeactivateGuard implements CanDeactivate<PatientRegistrationFormComponent> {
constructor() {}
canDeactivate(component: PatientRegistrationFormComponent) {
return component.isChangesSaved();
}
}
isChangesSaved()
是组件内部的一个方法。
public isChangesSaved(): Observable<boolean> {
if (this.isDirtyForm()) {
return this.confirmService.confirmUnsavedChanges();
}
return of(false);
}
这是错误,
ERROR Error: Uncaught (in promise): TypeError: Cannot read property
'isChangesSaved' of null TypeError: Cannot read property
'isChangesSaved' of null at
CanDeactivateGuard.push../src/app/core/database/database-cores/registry-core/guards/patient-registration.guard.ts.CanDeactivateGuard.canDeactivate
这是我的模块(延迟加载)
@NgModule({
imports: [
CommonModule,
RegistryRoutingModule,
ReactiveFormsModule,
FormsModule,
],
declarations: [
RegistryContainerComponent,
RegistryHomeComponent,
PatientRegistrationFormComponent, // component of interest ….
],
exports: [PatientRegistrationFormComponent],
schemas: [NO_ERRORS_SCHEMA],
providers: [
…fromGaurds.guards, // all my guards are loaded here….
{ provide: ErrorStateMatcher, useClass: ShowOnDirtyErrorStateMatcher },
ToastService,
],
})
export class RegistryModule {}
这是我的路由模块
const routes: Routes = [
{
path: '',
component: RegistryContainerComponent,
children: [
{
path: '',
component: RegistryHomeComponent,
},
{
path: 'patientregistration',
component: PatientRegistrationFormComponent,
canDeactivate: [fromGaurds.CanDeactivateGuard],
children: [
{
path: '',
component: PatientRegistrationFormComponent,
canActivate: [fromGaurds.PatientRegistryGuard],
canDeactivate: [fromGaurds.CanDeactivateGuard],
},
{
path: ':id',
component: PatientRegistrationFormComponent,
canActivate: [fromGaurds.PatientRegistryRecordGuard],
canDeactivate: [fromGaurds.CanDeactivateGuard],
},
],
},
],
},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class RegistryRoutingModule {}
这是错误还是接口实现错误?
更新
我厌倦了将守卫添加到延迟加载模块。
这是上面提到的子模块RegistryModule
的父模块,
const dbRoutes: Routes = [
{
path: '',
component: DbHomeComponent,
data: { preload: true },
canDeactivate: [fromGaurds.CanDeactivateGuard],
children: [
{ path: '', component: UsersDashboardComponent },
{
path: 'registry',
canActivate: [RoleGuardService],
data: { expectedRole: { roles: ['reg'] } },
loadChildren: '../database-cores/registry-core/modules/registry.module#RegistryModule',
},
{
path: 'cloudstorage',
canActivate: [RoleGuardService],
loadChildren:
'../database-cores/cloud-storage-core/modules/cloud-storage.module#CloudStorageModule',
},
],
},
];
@NgModule({
imports: [RouterModule.forChild(dbRoutes)],
exports: [RouterModule],
})
export class DbRoutingModule {}
@NgModule({
declarations: [
DbHeaderComponent,
DbFooterComponent,
DbHomeComponent,
UsersDashboardComponent,
],
imports: [
}),
],
exports: [],
providers: [
...fromGaurds.guards,
MDBSpinningPreloader,
ToastService,
DirectoryService,
],
schemas: [NO_ERRORS_SCHEMA],
})
export class DbModule {}
我修改了您的 stackblitz 以重现该问题。问题的核心是同一组件的同一个停用守卫被触发了两次。第二次触发时,该组件已被停用且不再存在,因此出现错误。
违规代码在 RegistryRoutingModule 中。父路由'patientregistration'
和子路由''
同时激活,使用同一个守卫。如果你移除其中一个守卫,它应该可以工作。根据您的用例,您可以从父级或子级中移除守卫,但是鉴于守卫将级联,您可以从所有子级中移除。
const routes: Routes = [
{
path: '',
component: RegistryContainerComponent,
children: [
{
path: '',
component: RegistryHomeComponent,
},
{
path: 'patientregistration',
component: PatientRegistrationFormComponent,
canDeactivate: [fromGaurds.CanDeactivateGuard],
children: [
{
path: '',
canActivate: [fromGaurds.PatientRegistryGuard]
},
{
path: ':id',
canActivate: [fromGaurds.PatientRegistryRecordGuard]
},
],
},
],
},
];
整理完毕。归功于 sliceofbytes
问题还在于在父路径和子路径中复制我的组件
以下配置也能正常工作。 canDeactivate
为两个子路径提供服务。我认为核心问题是我只有一个 PatientRegistrationFormComponent
实例为两条子路线提供服务。
Here 是一个回购。
const routes: Routes = [
{
path: '',
component: RegistryContainerComponent,
children: [
{
path: '',
component: RegistryHomeComponent,
},
{
path: 'patientregistration',
//component: PatientRegistrationFormComponent, <---- here was the core issue
children: [
{
path: '',
component: PatientRegistrationFormComponent,
canActivate: [fromGaurds.PatientRegistryGuard],
canDeactivate: [fromGaurds.CanDeactivateGuard],
},
{
path: ':id',
component: PatientRegistrationFormComponent,
canActivate: [fromGaurds.PatientRegistryRecordGuard],
canDeactivate: [fromGaurds.CanDeactivateGuard],
},
],
},
],
},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class RegistryRoutingModule {}
我正在懒惰地加载我的路线。我正在尝试根据文档使用 CanDeactivate
,但守卫似乎无法读取组件的属性或方法。
这是我的守卫,
@Injectable()
export class CanDeactivateGuard implements CanDeactivate<PatientRegistrationFormComponent> {
constructor() {}
canDeactivate(component: PatientRegistrationFormComponent) {
return component.isChangesSaved();
}
}
isChangesSaved()
是组件内部的一个方法。
public isChangesSaved(): Observable<boolean> {
if (this.isDirtyForm()) {
return this.confirmService.confirmUnsavedChanges();
}
return of(false);
}
这是错误,
ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'isChangesSaved' of null TypeError: Cannot read property 'isChangesSaved' of null at CanDeactivateGuard.push../src/app/core/database/database-cores/registry-core/guards/patient-registration.guard.ts.CanDeactivateGuard.canDeactivate
这是我的模块(延迟加载)
@NgModule({
imports: [
CommonModule,
RegistryRoutingModule,
ReactiveFormsModule,
FormsModule,
],
declarations: [
RegistryContainerComponent,
RegistryHomeComponent,
PatientRegistrationFormComponent, // component of interest ….
],
exports: [PatientRegistrationFormComponent],
schemas: [NO_ERRORS_SCHEMA],
providers: [
…fromGaurds.guards, // all my guards are loaded here….
{ provide: ErrorStateMatcher, useClass: ShowOnDirtyErrorStateMatcher },
ToastService,
],
})
export class RegistryModule {}
这是我的路由模块
const routes: Routes = [
{
path: '',
component: RegistryContainerComponent,
children: [
{
path: '',
component: RegistryHomeComponent,
},
{
path: 'patientregistration',
component: PatientRegistrationFormComponent,
canDeactivate: [fromGaurds.CanDeactivateGuard],
children: [
{
path: '',
component: PatientRegistrationFormComponent,
canActivate: [fromGaurds.PatientRegistryGuard],
canDeactivate: [fromGaurds.CanDeactivateGuard],
},
{
path: ':id',
component: PatientRegistrationFormComponent,
canActivate: [fromGaurds.PatientRegistryRecordGuard],
canDeactivate: [fromGaurds.CanDeactivateGuard],
},
],
},
],
},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class RegistryRoutingModule {}
这是错误还是接口实现错误?
更新
我厌倦了将守卫添加到延迟加载模块。
这是上面提到的子模块RegistryModule
的父模块,
const dbRoutes: Routes = [
{
path: '',
component: DbHomeComponent,
data: { preload: true },
canDeactivate: [fromGaurds.CanDeactivateGuard],
children: [
{ path: '', component: UsersDashboardComponent },
{
path: 'registry',
canActivate: [RoleGuardService],
data: { expectedRole: { roles: ['reg'] } },
loadChildren: '../database-cores/registry-core/modules/registry.module#RegistryModule',
},
{
path: 'cloudstorage',
canActivate: [RoleGuardService],
loadChildren:
'../database-cores/cloud-storage-core/modules/cloud-storage.module#CloudStorageModule',
},
],
},
];
@NgModule({
imports: [RouterModule.forChild(dbRoutes)],
exports: [RouterModule],
})
export class DbRoutingModule {}
@NgModule({
declarations: [
DbHeaderComponent,
DbFooterComponent,
DbHomeComponent,
UsersDashboardComponent,
],
imports: [
}),
],
exports: [],
providers: [
...fromGaurds.guards,
MDBSpinningPreloader,
ToastService,
DirectoryService,
],
schemas: [NO_ERRORS_SCHEMA],
})
export class DbModule {}
我修改了您的 stackblitz 以重现该问题。问题的核心是同一组件的同一个停用守卫被触发了两次。第二次触发时,该组件已被停用且不再存在,因此出现错误。
违规代码在 RegistryRoutingModule 中。父路由'patientregistration'
和子路由''
同时激活,使用同一个守卫。如果你移除其中一个守卫,它应该可以工作。根据您的用例,您可以从父级或子级中移除守卫,但是鉴于守卫将级联,您可以从所有子级中移除。
const routes: Routes = [
{
path: '',
component: RegistryContainerComponent,
children: [
{
path: '',
component: RegistryHomeComponent,
},
{
path: 'patientregistration',
component: PatientRegistrationFormComponent,
canDeactivate: [fromGaurds.CanDeactivateGuard],
children: [
{
path: '',
canActivate: [fromGaurds.PatientRegistryGuard]
},
{
path: ':id',
canActivate: [fromGaurds.PatientRegistryRecordGuard]
},
],
},
],
},
];
整理完毕。归功于 sliceofbytes
问题还在于在父路径和子路径中复制我的组件
以下配置也能正常工作。 canDeactivate
为两个子路径提供服务。我认为核心问题是我只有一个 PatientRegistrationFormComponent
实例为两条子路线提供服务。
Here 是一个回购。
const routes: Routes = [
{
path: '',
component: RegistryContainerComponent,
children: [
{
path: '',
component: RegistryHomeComponent,
},
{
path: 'patientregistration',
//component: PatientRegistrationFormComponent, <---- here was the core issue
children: [
{
path: '',
component: PatientRegistrationFormComponent,
canActivate: [fromGaurds.PatientRegistryGuard],
canDeactivate: [fromGaurds.CanDeactivateGuard],
},
{
path: ':id',
component: PatientRegistrationFormComponent,
canActivate: [fromGaurds.PatientRegistryRecordGuard],
canDeactivate: [fromGaurds.CanDeactivateGuard],
},
],
},
],
},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class RegistryRoutingModule {}