Angular中CanDeactivate自定义确认弹窗异常问题求助
Angular未保存数据自定义确认弹窗问题
我在Angular应用中实现未保存数据的自定义确认弹窗时遇到两个问题:
- 方案1:弹窗正常弹出,但所有背景元素消失,其余功能正常
- 方案2:背景元素正常,但不该显示弹窗时也会弹出,推测是返回Observable时未等待客户端响应导致的
以下是两种方案的CanDeactivate Guard实现代码、AlertDialogManager服务代码以及调用方法:
第一种方案代码
import { Injectable } from '@angular/core'; import { ActivatedRouteSnapshot, CanDeactivate, RouterStateSnapshot, UrlTree } from '@angular/router'; import { Observable } from 'rxjs/Observable'; import { TranslateService } from '@ngx-translate/core'; import { AlertDialogManager } from 'compiler-modules'; export interface ComponentCanDeactivate { canDeactivate: () => boolean | Observable<boolean>; pendingChangesMessage?: string; } @Injectable({ providedIn: 'root' }) export class PendingChangesGuardGuard implements CanDeactivate<ComponentCanDeactivate> { private defaultPendingMessage: string; constructor(translateService: TranslateService, private ad: AlertDialogManager) { translateService.get('GENERIC.PENDING_CHANGES') .subscribe(t => this.defaultPendingMessage = t); } canDeactivate(component: ComponentCanDeactivate, currentRoute: ActivatedRouteSnapshot, currentState: RouterStateSnapshot, nextState?: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree { return component.canDeactivate() ? true : this.ad.confirm("ty", component.pendingChangesMessage || this.defaultPendingMessage) } }
第二种方案代码
import { Injectable } from '@angular/core'; import { ActivatedRouteSnapshot, CanDeactivate, RouterStateSnapshot, UrlTree } from '@angular/router'; import { Observable } from 'rxjs/Observable'; import { TranslateService } from '@ngx-translate/core'; import { AlertDialogManager } from 'compiler-modules'; import { first } from 'rxjs/operators'; export interface ComponentCanDeactivate { canDeactivate: () => boolean | Observable<boolean>; pendingChangesMessage?: string; } @Injectable({ providedIn: 'root' }) export class PendingChangesGuardGuard implements CanDeactivate<ComponentCanDeactivate> { private defaultPendingMessage: string; constructor(translateService: TranslateService, private ad: AlertDialogManager) { translateService.get('GENERIC.PENDING_CHANGES') .subscribe(t => this.defaultPendingMessage = t); } canDeactivate(component: ComponentCanDeactivate, currentRoute: ActivatedRouteSnapshot, currentState: RouterStateSnapshot, nextState?: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree { let t :boolean; this.ad.confirm("ty", component.pendingChangesMessage || this.defaultPendingMessage).subscribe(res => (t = res)) return component.canDeactivate() ? true : t; } }
AlertDialogManager服务代码
import { Injectable, TemplateRef } from '@angular/core'; import { MatDialog } from '@angular/material'; import { Observable } from 'rxjs/Observable'; import { AlertDialogViewComponent } from './alert-dialog-view/alert-dialog-view.component'; import { AlertConfig, AlertInputData } from './alert-dialog.models'; @Injectable({ providedIn: 'root' }) export class AlertDialogManager { constructor(private dialog: MatDialog) { } alert(title: string, description: string, buttonText: string = 'OK', bodyTemplateRef: TemplateRef<any> = null, bodyTemplateContext: any = null, config: AlertConfig = null): Observable<void> { const alertRef = this.dialog.open<AlertDialogViewComponent, AlertInputData, void>(AlertDialogViewComponent, { disableClose: true, panelClass: 'dialog-container-small', data: { title: title, description: description, buttonText: buttonText, type: 'alert', bodyTemplateRef: bodyTemplateRef, bodyTemplateContext: bodyTemplateContext }, ...config }); return alertRef.afterClosed(); } confirm(title: string, question: string, buttonText: string = 'OK', cancelButtonText: string = 'Anuluj', bodyTemplateRef: TemplateRef<any> = null, bodyTemplateContext: any = null, config: AlertConfig = null): Observable<boolean> { const alertRef = this.dialog.open<AlertDialogViewComponent, AlertInputData, boolean>(AlertDialogViewComponent, { disableClose: true, panelClass: 'dialog-container-small', data: { title: title, description: question, buttonText: buttonText, cancelButtonText: cancelButtonText, type: 'confirm', bodyTemplateRef: bodyTemplateRef, bodyTemplateContext: bodyTemplateContext }, ...config }); return alertRef.afterClosed(); } }
调用方法
@HostListener('window:beforeunload') canDeactivate(): Observable<boolean> | boolean { return !this.issueViewComponent ? true : this.issueViewComponent.canDeactivate(); }
截图说明
- 新增笔记视图:正常的页面展示状态,包含所有界面元素
- 存在未保存更改时背景消失:弹窗弹出后,页面背景元素全部消失,仅弹窗可见
内容的提问来源于stack exchange,提问作者Kacper
相关产品推荐
相关产品推荐

