Search code examples
angularrxjskendo-uimodal-dialogcandeactivate

How to make CanDeactivate work with kendo-ui angular dialog


I'm trying to implement this CanDeactivate Route Guard using kendo-ui angular dialog instead of the window.confirm,

It works fine with window.confirm but with kendo-ui dialog only the second time I execute the dialog. The first time the method this.confirmCanExitDialog() returns false even if I click Yes and the second time I execute the dialog by trying to navigate somewhere else, it returns true.

The problem I have is that this line return this._canExitResult$$.value; executes before the dialog.result even if I make the method return an Observable<boolean>, the result is always false (initial value). Please help.

kendo-ui dialog

 public canExit(): boolean {
    return this.form.dirty ? this.confirmCanExitDialog() : true;
  }

 private confirmCanExitDialog(): boolean {
    const dialogRef = this.dialogService.open({
      content: ConfirmDialogComponent,
    });
    const confirmDialog = dialogRef.content.instance as ConfirmDialogComponent;
    confirmDialog.message = 'Confirmation.CanExit';

    dialogRef.result.subscribe((result: DialogCloseResult) => {
      if (result === 'Yes') {
        this._canExitResult$$.next(true);
      }
      if (result === 'No') {
        this._canExitResult$$.next(false);
      }
    });
    return this._canExitResult$$.value;
  }

Solution

  • window.confirm is a blocking call and this is why this code works:

     public canExit(): boolean {
        return this.form.dirty ? window.confirm() : true;
     }
    

    If you want to use non-blocking dialog like kendo, then you have to return Observable/Promise:

    canDeactivate(component: any, currentRoute: ActivatedRouteSnapshot, currentState: RouterStateSnapshot, nextState: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
        return this.form.dirty ? this.confirmCanExitDialog() : of(true);
    }
    
    
    private confirmCanExitDialog(): Observable<boolean> {
        const dialogRef = this.dialogService.open({
          content: ConfirmDialogComponent,
        });
        const confirmDialog = dialogRef.content.instance as ConfirmDialogComponent;
        confirmDialog.message = 'Confirmation.CanExit';
    
        return dialogRef.result.pipe(map(x => x === 'Yes'));
      }