Close @angular/material Dialog U
2018-10-30 本文已影响0人
forks1990
By default angular material dialog closed on browser navigation, such as back/forward. Normally it is good, in mobile phone environments, user may want back operation close opened dialog only, keep current angular router entry unchanged.
Disable closeOnNavigation
option
const dialogRef = this.dialog.open<YourDialogComponent>(YourDialogComponent, {
closeOnNavigation: false,
});
Disable closeOnNavigation
option tells angular dialog service do not close dialog when user back/forward browser, this happens before @angular/router.
Create @angular/router Deactivate Guard
@Injectable({
providedIn: 'root',
})
export class CloseDialogOnRouteService implements CanDeactivate<any> {
constructor(private dialog: MatDialog) { }
canDeactivate(): Observable<boolean> | Promise<boolean> | boolean {
if (this.dialog.openDialogs.length === 0) {
// If current no dialog open, pops current angular router entry normally.
return true;
}
// close and wait all dialogs closed.
this.dialog.closeAll();
return this.dialog.afterAllClosed.pipe(first(), map(() => {
// abort leave current route, user only want to close popup, not current route
return false;
}));
}
}
Fix Bug of @angular/router
A bug of @angular/router https://github.com/angular/angular/issues/13586 if CanDeactivate()
returns false, browser history not synced with @angular/router state, to fix, we can re-forward browser history as https://github.com/angular/angular/issues/13586#issuecomment-402250031
@Injectable({
providedIn: 'root',
})
export class CloseDialogOnRouteService implements CanDeactivate<any> {
constructor(private dialog: MatDialog,
private readonly location: Location,
private readonly router: Router,
) { }
canDeactivate(_: any, currentRoute: ActivatedRouteSnapshot): Observable<boolean> | Promise<boolean> | boolean {
if (this.dialog.openDialogs.length === 0) {
return true;
}
this.dialog.closeAll();
return this.dialog.afterAllClosed.pipe(first(), map(() => {
const currentUrlTree = this.router.createUrlTree([], currentRoute);
const currentUrl = currentUrlTree.toString();
this.location.go(currentUrl);
return false;
}));
}
}