Angular 2/4 阻止用户在更改未保存时离开组件
Angular 2/4 prevent user to leave component if changes not saved
我有这个界面用来防止用户离开页面
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 的(组件:ComponentCanDeactivate)始终为 null,所以我收到一条错误消息
无法调用 null 的 canDeactivate()
我的路由中也有这个设置
path: 'dashboard',
canDeactivate: [PendingChangesGuard],
loadChildren: './views/dashboard/dashboard.module#DashboardModule'
谁能告诉我我做错了什么?
在您的 PendingChangesGuard 中,尝试注入组件本身,而不是接口:
export class PendingChangesGuard implements CanDeactivate<DashboardComponent> {
constructor() {}
canDeactivate(component: DashboardComponent): boolean {
...
}
您不能使用 Angular DI 注入接口,因为接口只是 Typescript 结构,不存在于编译过程生成的 Javascript 代码中。
有关详细信息,请查看 this SO 问题。
我是这样实现的
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;
});
}
问题是由延迟加载引起的
而不是在您的应用程序路由中使用它:
path: 'dashboard',
canDeactivate: [PendingChangesGuard], <-- causing issue
loadChildren: './views/dashboard/dashboard.module#DashboardModule'
您需要将应用路由中的canDeactive去掉,移到模块路由中。
const routes: Routes = [
{
path: '',
component: DashboardComponent,
canDeactivate: [ PendingChangesGuard ]
}
我有这个界面用来防止用户离开页面
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 的(组件:ComponentCanDeactivate)始终为 null,所以我收到一条错误消息
无法调用 null 的 canDeactivate()
我的路由中也有这个设置
path: 'dashboard',
canDeactivate: [PendingChangesGuard],
loadChildren: './views/dashboard/dashboard.module#DashboardModule'
谁能告诉我我做错了什么?
在您的 PendingChangesGuard 中,尝试注入组件本身,而不是接口:
export class PendingChangesGuard implements CanDeactivate<DashboardComponent> {
constructor() {}
canDeactivate(component: DashboardComponent): boolean {
...
}
您不能使用 Angular DI 注入接口,因为接口只是 Typescript 结构,不存在于编译过程生成的 Javascript 代码中。
有关详细信息,请查看 this SO 问题。
我是这样实现的
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;
});
}
问题是由延迟加载引起的
而不是在您的应用程序路由中使用它:
path: 'dashboard',
canDeactivate: [PendingChangesGuard], <-- causing issue
loadChildren: './views/dashboard/dashboard.module#DashboardModule'
您需要将应用路由中的canDeactive去掉,移到模块路由中。
const routes: Routes = [
{
path: '',
component: DashboardComponent,
canDeactivate: [ PendingChangesGuard ]
}