0

I need to create canDeactiovateGuard to prevent user losing form data when trying to leave form page. This code below doesn't work since return canDeactivate works before canDeactivate = confirmed. I'm not sure how to fix this.

@Injectable()
export class CanDeactivateGuard implements CanDeactivate<Component> {

  canDeactivate(component: Component): boolean {
    let canDeactivate: boolean;
    if (component.formValueChanged) {
        component.confirmService.confirm("You have unsaved data. Are you sure?")
            .pipe(first())
            .subscribe((confirmed: boolean) => {
                canDeactivate = confirmed;
            });
    } else {
        canDeactivate = true;
    }
    return canDeactivate;
  }

}
Olga
  • 119
  • 1
  • 1
  • 12

1 Answers1

2

Try instead to return an Observable<boolean>. This can be done via operators such as RxJS map. Either way, in guards such as CanDeactivate or CanActivate, basically you would never use subscribe() as you can't return anything from within a subscribe() and instead return Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree:

import { map } from 'rxjs/operators';

@Injectable()
export class CanDeactivateGuard implements CanDeactivate<Component> {

  canDeactivate(component: Component): Observable<boolean> | boolean {
    if (component.formValueChanged) {
        // Return the observable instead of the subscription
        return component.confirmService.confirm("You have unsaved data. Are you sure?")
            .pipe(first())
            // You may be able to remove map() assuming confirm() always returns Observable<boolean>
            .map((confirmed: boolean) => confirmed);
    }

    return false;
  }
}
Dharman
  • 30,962
  • 25
  • 85
  • 135
Alexander Staroselsky
  • 37,209
  • 15
  • 79
  • 91