为什么不能取消激活Guard无法读取组件中的方法?

时间:2018-08-20 03:07:47

标签: angular angular-router-guards

我正在懒惰地装载我的路线。我正在尝试根据文档使用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);
  }

这是错误

  

错误错误:未捕获(承诺):TypeError:无法读取属性   TypeError的“ isChangesSaved”:无法读取属性   的“ isChangesSaved”为null   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 {}

2 个答案:

答案 0 :(得分:1)

我修改了您的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]
          },
        ],
      },
    ],
  },
];

答案 1 :(得分:1)

已排序。功劳归于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 {}