Угловая 2/4 не позволяет пользователю покинуть компонент, если изменения не сохранены
У меня есть этот интерфейс, который я использую, чтобы не дать пользователю покинуть страницу
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;
}
Моя проблема в том, что мой компонент -> (component: ComponentCanDeactivate) из PendingChangesGuard всегда нулевой, поэтому я получаю сообщение об ошибке
Невозможно вызвать canDeactivate() со значением NULL
У меня также есть эта настройка в моей маршрутизации
path: 'dashboard',
canDeactivate: [PendingChangesGuard],
loadChildren: './views/dashboard/dashboard.module#DashboardModule'
Может кто-нибудь сказать мне, что я делаю не так?
3 ответа
Проблема была вызвана отложенной загрузкой
Вместо того, чтобы иметь это в вашем маршрутизации приложения:
path: 'dashboard',
canDeactivate: [PendingChangesGuard], <-- causing issue
loadChildren: './views/dashboard/dashboard.module#DashboardModule'
Вам нужно удалить canDeactive из маршрутизации приложения и переместить его в маршрутизацию модуля.
const routes: Routes = [
{
path: '',
component: DashboardComponent,
canDeactivate: [ PendingChangesGuard ]
}
Я реализую так
Выключена-сторожевой 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;
});
}
В вашем PendingChangesGuard попробуйте ввести сам компонент, а не интерфейс:
export class PendingChangesGuard implements CanDeactivate<DashboardComponent> {
constructor() {}
canDeactivate(component: DashboardComponent): boolean {
...
}
Вы не можете внедрить интерфейс, используя Angular DI, так как интерфейсы являются просто конструкциями Typescript и не существуют в коде Javascript, созданном в процессе компиляции.
Для получения дополнительной информации, посмотрите на этот вопрос SO.