'Angular 6: simple confirmation on page leaving

I need to make a simple confirm window and I saw a lot of examples of how to do it with extra actions (like waiting until file uploading of form is not field). But I need just make a default confirm window with a default text (like in a pic below) to show it when the user wants to leave from the current page. And I can't completely understand what logic should I proved inside handling before unload event.

image example

I'm recently sorry if it a dup of some question, however, I didn't find any solution. So I have:

example.guard.ts

export interface CanComponentDeactivate {
    canDeactivate: () => Observable<boolean> | boolean;
}

@Injectable()
export class ExampleGuard implements CanDeactivate<CanComponentDeactivate> {

    constructor() { }

    canDeactivate(component: CanComponentDeactivate): boolean | Observable<boolean> {
        return component.canDeactivate() ?
            true :
            confirm('message'); // <<< does confirm window should appear from here?
    }
}

example.component.ts

export class ExampleComponent implements CanComponentDeactivate {

    counstructor() { }

    @HostListener('window:beforeunload', ['$event'])
        canDeactivate($event: any): Observable<boolean> | boolean {
            if (!this.canDeactivate($event)) {
                // what should I do here?
            }
        }
}

It would be wonderful if you provide a sample of code but I appreciate any kind of help.



Solution 1:[1]

You should differentiate beforeunload native event on window and canDeactivate guard. First one is being triggered when you are trying to close tab/window. So that when it is triggered you can confirm(...) user and execute event.preventDefault() on it to cancel closing tab/window.

Talking about CanDeactivate guard it should return an observable/promise/plain-value of boolean which will tell you if you can deactivate current route.

So it is much better to separate two methods (one for beforeunload and second one for the guard). Because if you want then change behavior to not just use native confirm but your custom modal window the default event handler for beforeunload won't work as it handles sync code. So for beforeunload you can use confirm only to ask user not to leave the page.

loading = true;
@HostListener('window:beforeunload', ['$event'])
canLeavePage($event: any): Observable<void> {
  if(this.loading && confirm('You data is loading. Are you sure you want to leave?')) {
    $event.preventDefault();
  }
}

Guard on the other hand wants boolean to be returned (or Promise, or Observable). So here you can just return the result of your condition:

canDeactivate(): boolean {
  return this.loading && confirm('You data is loading. Are you sure you want to leave?');
}

So that in your CanDeactivate guard it will be used like return component.canDeactivate()

Solution 2:[2]

If the requirement is default window confirmation message. Then it is achievable by below lines of code.

/**
 * Browser's default confirmation dialog box.
 */
  @HostListener('window:beforeunload')
  defaultConfirmation(): boolean {
    if (!DIRTY_FORM_CHECK) return true;
    else return false;
  }

Output:

enter image description here

Default confirmation dialog get appear if dirty check return true. In case of no dirty situation, pop-up will not appear.

Hope this might help someone. Thanks.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2