Search code examples
angulartypescriptasynchronousasync-awaitcandeactivate

Angular 11: Make canDeactivate observable wait for nested function


I'm trying to replace my browser alert with a custom one using Material dialog. If the user tries to navigate away from the form with unsaved changes, the custom alert shows. But I need to wait (pause the function) until the user clicks an option to return the value.

discardChangesAlertResult: boolean;

canDeactivate(): Observable<boolean> | Promise<boolean> | boolean {
    if (this.hasBeenEdited) {

        const dialogRef = this.dialog.open(DiscardChangesComponent, {panelClass: 'alert'});
        
        dialogRef.afterClosed().subscribe(result => {
            if (this.discardChangesService.discardChangesAlert) {
                this.hasBeenEdited = false;
                this.discardChangesAlertResult = true;
            } else {
                this.discardChangesAlertResult = false;
            } 
        });

        return this.discardChangesAlertResult; // I need this line to wait for user input
    } else {
        return true;
    }
}

Solution

  • you have to return Observable for that.

    canDeactivate(): Observable<boolean> | Promise<boolean> | boolean {
        if (!this.hasBeenEdited) {
            return true;
        }
        return this.dialog
            .open(DiscardChangesComponent, {panelClass: 'alert'})
            .afterClosed()
            .pipe(map(result => {
                if (this.discardChangesService.discardChangesAlert) {
                    this.hasBeenEdited = false;
                }
                return !!this.discardChangesService.discardChangesAlert;
            });
    }