【问题标题】:Angular 2/4 prevent user to leave component if changes not saved如果未保存更改,Angular 2/4 会阻止用户离开组件
【发布时间】:2018-05-18 08:36:30
【问题描述】:

我有这个界面用来防止用户离开页面

export interface ComponentCanDeactivate {
  canDeactivate: () => boolean;
}

@Injectable()
export class PendingChangesGuard implements CanDeactivate<ComponentCanDeactivate> {
  canDeactivate(component: ComponentCanDeactivate): boolean {
    return  component.canDeactivate() ?
     //code : //more code
  }
}

在我的一个组件中,我有以下代码

export class DashboardComponent implements ComponentCanDeactivate{
  @HostListener('window:beforeunload')
  canDeactivate(): boolean {
    return !this.isDirty;
  }

我的问题是来自 PendingChangesGuard 的我的组件 -> (component: ComponentCanDeactivate) 始终为空,所以我收到一条错误消息

不能调用null的canDeactivate()

我的路由中也有这个设置

 path: 'dashboard',
        canDeactivate: [PendingChangesGuard],
        loadChildren: './views/dashboard/dashboard.module#DashboardModule'

谁能告诉我我做错了什么?

【问题讨论】:

  • @MilanRaval 是的,我实现了 ComponentCanDeactivate 并重写了函数 canDeactive(): boolean。 (您可以在我的帖子中间看到代码)。它仅在表单脏或不脏时才返回

标签: angular angular-routing angular-router-guards


【解决方案1】:

在你的 PendingChangesGuard 中,尝试注入组件本身,而不是接口:

export class PendingChangesGuard implements CanDeactivate<DashboardComponent> {
  constructor() {}
  canDeactivate(component: DashboardComponent): boolean {
  ...
  }

您不能使用 Angular DI 注入接口,因为接口只是 Typescript 构造,不存在于编译过程生成的 Javascript 代码中。

有关更多信息,请查看this SO question。

【讨论】:

  • 感谢您的回复,我试过了,我得到了同样的错误:TypeError: Cannot read property 'canDeactivate' of null
  • 我认为你需要在你的路由设置中声明一个组件才能让守卫工作。像:路径:'dashboard',canDeactivate:[PendingChangesGuard],组件:DashboardComponent 我想你可以做的是在仪表板模块路由配置中设置你的后卫'lower'。让我知道它是否有效。
  • 这是我的路由:路径:'dashboard',canDeactivate:[PendingChangesGuard],loadChildren:'./views/dashboard/dashboard.module#DashboardModule'}
  • 是的,我从问题中看到了这一点。据我了解,如果不在路由配置中指定组件,就无法添加依赖于某些组件逻辑的路由保护,这就是为什么总是会出现异常的原因。
【解决方案2】:

我是这样实现的

Deactive-guard-service.ts

export interface CanComponentDeactivate {
  canDeactivate: () => Observable<boolean> | Promise<boolean> | boolean;
}

@Injectable()
export class DeactivateGuardService implements  CanDeactivate<CanComponentDeactivate>{

  canDeactivate(component: CanComponentDeactivate) {
    return component.canDeactivate ? component.canDeactivate() : true;
  }
}

Component.ts

checkSave(): Promise<boolean> {
    var prom = new Promise<boolean>((resolve, reject) => {
      //check saved change
        if(saved) resolve(true);
        else reject(false);
    });
    return prom;
  }

  canDeactivate(): Promise<boolean> {

    return this.checkSave().catch(function () {
      return false;
    });
  }

【讨论】:

  • 我尝试像你一样实施,它给了我同样的错误。它告诉我:TypeError: Cannot read property 'canDeactivate' of null
  • 我认为您的问题是因为您使用的是延迟加载模块。可以参考这个话题github.com/angular/angular/issues/16868尝试把CanDeactive放到DashboardModule的主路由中
  • 感谢@Dakota,这就是问题所在!
【解决方案3】:

问题是由延迟加载引起的

而不是在您的应用路由中使用它:

path: 'dashboard',
        canDeactivate: [PendingChangesGuard], <-- causing issue
        loadChildren: './views/dashboard/dashboard.module#DashboardModule'

您需要从应用路由中移除canDeactive,并将其移动到模块路由中。

const routes: Routes = [
  {
    path: '',
    component: DashboardComponent,
    canDeactivate: [ PendingChangesGuard ]
  }

【讨论】:

  • 谢谢!这就是我所缺少的!
猜你喜欢
  • 2023-04-01
  • 1970-01-01
  • 2018-09-23
  • 2016-06-25
  • 1970-01-01
  • 2018-12-23
  • 1970-01-01
  • 2022-11-16
  • 1970-01-01
相关资源
最近更新 更多