0

I've been facing problem with custom dialog confirmation about losing data in my app. I tried 2 approaches. First one results in dialog oppening and all the background elements disappear, but besides that everything works. Second approach results with no background disappearing but the dialog show even if it shouldn't. I believe that the second problem is caused by returning the observable and not being able to wait for the client response.

canDeactivate Guard in 1st approach

import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanDeactivate, RouterStateSnapshot, UrlTree } from '@angular/router';
import { Observable } from 'rxjs/Observable';
import { TranslateService } from '@ngx-translate/core';
import { AlertDialogManager } from 'compiler-modules';


export interface ComponentCanDeactivate {
  canDeactivate: () => boolean | Observable<boolean>;
  pendingChangesMessage?: string;
}

@Injectable({
  providedIn: 'root'
})
export class PendingChangesGuardGuard implements CanDeactivate<ComponentCanDeactivate> {

  private defaultPendingMessage: string;

  constructor(translateService: TranslateService, private ad: AlertDialogManager) {
    translateService.get('GENERIC.PENDING_CHANGES')
      .subscribe(t => this.defaultPendingMessage = t);
  }

  canDeactivate(component: ComponentCanDeactivate,
                currentRoute: ActivatedRouteSnapshot,
                currentState: RouterStateSnapshot,
                nextState?: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {

    return component.canDeactivate() ? true : this.ad.confirm("ty", component.pendingChangesMessage || this.defaultPendingMessage)
    
  }

}

2nd approach

import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanDeactivate, RouterStateSnapshot, UrlTree } from '@angular/router';
import { Observable } from 'rxjs/Observable';
import { TranslateService } from '@ngx-translate/core';
import { AlertDialogManager } from 'compiler-modules';
import { first } from 'rxjs/operators';

export interface ComponentCanDeactivate {
  canDeactivate: () => boolean | Observable<boolean>;
  pendingChangesMessage?: string;
}

@Injectable({
  providedIn: 'root'
})

export class PendingChangesGuardGuard implements CanDeactivate<ComponentCanDeactivate> {

  private defaultPendingMessage: string;

  constructor(translateService: TranslateService, private ad: AlertDialogManager) {
    translateService.get('GENERIC.PENDING_CHANGES')
      .subscribe(t => this.defaultPendingMessage = t);
  }

  canDeactivate(component: ComponentCanDeactivate,
                currentRoute: ActivatedRouteSnapshot,
                currentState: RouterStateSnapshot,
                nextState?: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {


                  let t :boolean;
              this.ad.confirm("ty", component.pendingChangesMessage || this.defaultPendingMessage).subscribe(res => (t = res))
    return component.canDeactivate() ? true :
      t;
  }

}

AlertDialogmanager service

import { Injectable, TemplateRef } from '@angular/core';
import { MatDialog } from '@angular/material';
import { Observable } from 'rxjs/Observable';

import { AlertDialogViewComponent } from './alert-dialog-view/alert-dialog-view.component';
import { AlertConfig, AlertInputData } from './alert-dialog.models';

@Injectable({
  providedIn: 'root'
})
export class AlertDialogManager {

  constructor(private dialog: MatDialog) { }

  alert(title: string, description: string, buttonText: string = 'OK',
        bodyTemplateRef: TemplateRef<any> = null, bodyTemplateContext: any = null, config: AlertConfig = null): Observable<void> {
    const alertRef = this.dialog.open<AlertDialogViewComponent, AlertInputData, void>(AlertDialogViewComponent, {
      disableClose: true,
      panelClass: 'dialog-container-small',
      data: {
        title: title,
        description: description,
        buttonText: buttonText,
        type: 'alert',
        bodyTemplateRef: bodyTemplateRef,
        bodyTemplateContext: bodyTemplateContext
      },
      ...config
    });

    return alertRef.afterClosed();
  }

  confirm(title: string, question: string, buttonText: string = 'OK', cancelButtonText: string = 'Anuluj',
          bodyTemplateRef: TemplateRef<any> = null, bodyTemplateContext: any = null, config: AlertConfig = null): Observable<boolean> {
    const alertRef = this.dialog.open<AlertDialogViewComponent, AlertInputData, boolean>(AlertDialogViewComponent, {
      disableClose: true,
      panelClass: 'dialog-container-small',
      data: {
        title: title,
        description: question,
        buttonText: buttonText,
        cancelButtonText: cancelButtonText,
        type: 'confirm',
        bodyTemplateRef: bodyTemplateRef,
        bodyTemplateContext: bodyTemplateContext
      },
      ...config
    });

    return alertRef.afterClosed();
  }

}

and i call the method in

  @HostListener('window:beforeunload')
  canDeactivate(): Observable<boolean> | boolean {
    return !this.issueViewComponent ? true : this.issueViewComponent.canDeactivate();
  }

these are my solutions

the add note view

but when i have unsaved changes background of addview disappears

Kacper
  • 1
  • 1
  • I don't really understand the issue on the 1st solution. For the 2nd one you shouldnt call `subscribe` but return the observable using `switchMap` for example – Matthieu Riegler Jul 20 '23 at 08:46
  • in the first solution i have unsaved notes and if i want to leave the page etc. i want the notes to be visible under the dialog. Instead the notes disappear and the diaolg is the only thing i see – Kacper Jul 20 '23 at 09:09
  • PendingChangesGuardGuard by itself can not make anything to disappear, can you at least add a screenshot of what is happening? – kemsky Jul 20 '23 at 12:47
  • added screens hope it helps – Kacper Jul 20 '23 at 14:01
  • @kemsky i dropped some screenshots – Kacper Jul 24 '23 at 12:29
  • Use devtools to inspect page, maybe dialog is fullscreen, if it is not than there is something else in your code that does it (maybe navigation is triggered somehow) – kemsky Jul 25 '23 at 20:49

0 Answers0