Angular:关闭Mat-Dialog后如何向CanDeactivate Guard返回值
Looking at your code, the main issue is that your confirmDialog() method returns a Subscription (from calling subscribe() on dialogRef.afterClosed()) instead of the Observable<boolean> that the CanDeactivate guard expects. This means the guard can’t properly handle the asynchronous dialog result to control navigation.
Here’s how to fix this step by step:
1. Update the confirmDialog() method in UnsavedChangesComponent.ts
Instead of subscribing directly, return the observable from afterClosed() and use pipe(tap(...)) to handle save/cancel logic as a side effect. This keeps the observable chain intact for the guard to use:
import { tap } from 'rxjs/operators'; import { Observable } from 'rxjs'; // ... confirmDialog(): Observable<boolean> { const dialogRef = this.dialog.open(ConfirmDialogComponent, { width: '450px', }); return dialogRef.afterClosed().pipe( tap(result => { if (result === true) { // Execute save action when user confirms this.save(); } // No extra logic needed for false result—we just let the observable pass the value to the guard }) ); }
2. Why this works
dialogRef.afterClosed()returns anObservable<any>that emits the dialog’s close result (true/falsein your setup).- Using
tap()lets us run the save logic without modifying the emitted value. The observable will still pass throughtrueorfalse, which the guard uses to decide navigation:- If
result === true: We save changes, then the guard receivestrueto allow navigation - If
result === false: The guard receivesfalseto block navigation (keeping the user on the page)
- If
3. Your DeactivateGuard stays unchanged
The guard is already configured to handle Observable<boolean>, so no modifications are needed here:
export class DeactivateGuard implements CanDeactivate<UnsavedChangesComponent> { canDeactivate( component: UnsavedChangesComponent, currentRoute: ActivatedRouteSnapshot, currentState: RouterStateSnapshot, nextState?: RouterStateSnapshot): boolean | Observable<boolean> | Promise<boolean> { if (component.isDirty) { return component.confirmDialog(); } else { return true; } } }
4. Confirm your dialog component logic
Double-check that your ConfirmDialogComponent closes with the correct values to match your intended flow:
confirmDialog.ts:
import { MatDialogRef } from '@angular/material/dialog'; // ... constructor(public dialogRef: MatDialogRef<ConfirmDialogComponent>) {} save(){ this.dialogRef.close(true); } cancel() { this.dialogRef.close(false); }
confirmDialog.html:
<button mat-button color="primary" (click)="save()">Save Changes</button> <button mat-button color="warn" (click)="cancel()">Stay on Page</button>
(Adjust button text if needed to align with your user-facing labels)
This setup ensures the guard correctly reacts to the user’s dialog choice: saving changes before navigation if they select "Save", or keeping them on the page if they select "Cancel".
内容的提问来源于stack exchange,提问作者Dinesh Kannan

