Angular 2/4如何防止用户离开组件而未保存更改?

7

我有一个界面,用于防止用户离开页面

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;
  }

我的问题是,我的组件 -> (组件:ComponentCanDeactivate) 在PendingChangesGuard中总是为空,所以我会得到一个错误,显示无法调用null的canDeactivate()。
我在我的路由设置中也有这个设置。
 path: 'dashboard',
        canDeactivate: [PendingChangesGuard],
        loadChildren: './views/dashboard/dashboard.module#DashboardModule'

有人可以告诉我我做错了什么吗?

(这段文字是关于IT技术的)

@MilanRaval 是的,我实现了 ComponentCanDeactivate 并重写了函数 canDeactive(): boolean。(你可以在我的帖子中间看到代码)。它只返回表单是否被修改过。 - user9052661
3个回答

9
问题是由懒加载引起的。
不要在应用程序路由中添加此内容:
path: 'dashboard',
        canDeactivate: [PendingChangesGuard], <-- causing issue
        loadChildren: './views/dashboard/dashboard.module#DashboardModule'

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

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

谢谢!这就是我所缺少的! - redOctober13

0
在你的PendingChangesGuard中,尝试注入组件本身,而不是接口:
export class PendingChangesGuard implements CanDeactivate<DashboardComponent> {
  constructor() {}
  canDeactivate(component: DashboardComponent): boolean {
  ...
  }

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

如需更多信息,请查看this SO问题。


谢谢回复,我尝试了一下,得到了相同的错误,即:TypeError: 无法读取 null 的属性 'canDeactivate'。 - user9052661
我认为你需要在路由设置中声明一个组件才能使守卫起作用。类似于: path: 'dashboard', canDeactivate: [PendingChangesGuard], component: DashboardComponent你可以将守卫在仪表板模块路由配置中设置“低一些”。我想你可以试试,看看是否有效。 - Fjut
这是我在路由中的设置: 路径:'dashboard', canDeactivate:[PendingChangesGuard], loadChildren:'./views/dashboard/dashboard.module#DashboardModule' - user9052661
是的,我从问题中看到了这一点。据我理解,如果没有在路由配置中指定组件,您无法添加依赖于某些组件逻辑的路由守卫,这就是为什么您总是会收到异常的原因。 - Fjut

0
我是这样实现的。

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: 无法读取 null 的 'canDeactivate' 属性。 - user9052661
我认为你的问题是因为你正在使用懒加载模块。你可以参考这个主题 https://github.com/angular/angular/issues/16868 尝试将CanDeactive放入DashboardModule的主路由中。 - Dakota
谢谢 @Dakota,那就是问题所在! - user9052661

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接