Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 556
hofshteyn Avatar asked Jan 15 '19 13:01

hofshteyn


1 Answers

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()

like image 77
Danil Gudz Avatar answered Oct 18 '22 09:10

Danil Gudz