3

I want to save changes just before the user close the window, but it don't works when I quit the tab. I'm using router's canDeactivate method and it works when I refresh my page with F5, but when I close the tab datas are not saved. Here is my canDeactivate function in my component :

@HostListener('window:beforeunload')
canDeactivate(): Observable<boolean> | boolean {
    let subject = new Subject<boolean>();
    let observable = subject.asObservable();

    this.service.save(this.data).then(() => {
        subject.next(true);
    });

    return observable.first();
}

I already tried this too :

@HostListener('window:beforeunload')
canDeactivate(): Observable<boolean> | boolean {
    let xmlhttp = new XMLHttpRequest();   // new HttpRequest instance
    xmlhttp.withCredentials = false;
    xmlhttp.open("PUT", "http://localhost:8080/rest/api");
    xmlhttp.setRequestHeader("Content-Type", "application/json");
    xmlhttp.setRequestHeader("Accept", "application/json");
    xmlhttp.send(this.data);

    return false;
}
Mattew Eon
  • 1,722
  • 1
  • 21
  • 38

2 Answers2

3

The window:beforeunload is a synchronous event. If you perform an async action within the event listener the event will complete before your async action. That is why your http request is never made.

Unfortunately I could not find any method for forcing Angular 2's HTTP library to be performed synchronously. I was forced to import JQUERY and use AJAX.

                // the http call must be synchronous.
                // the 'unload' event won't wait for async
                // angular's http doesn't support synchronous requests
                // this is why we use JQUERY + AJAX
                $.ajax({
                    type: 'PUT',
                    async: false,
                    url: this.url
                });
Logic01
  • 115
  • 1
  • 7
0
@HostListener('window:beforeunload', ['$event'])
handler(event) {
  ...your warning
}

See it in action here link

Rahul Singh
  • 19,030
  • 11
  • 64
  • 86
  • This solution let the user decide if he wants to quit or not, I don't want him to cancel my http call – Mattew Eon Aug 01 '17 at 09:07
  • 1
    There's no option to send an async http call to the server and wait for it before closing the window. You could only inform the user that he's having unsaved changes. – cyr_x Aug 01 '17 at 09:10
  • @MattewEon i am not quite sure if this is possible it's a browser limitation but i searched on SO you can check this [link](https://stackoverflow.com/questions/38999842/angular-2-execute-code-when-closing-window) . not quite sure if this will help solve the issue – Rahul Singh Aug 01 '17 at 09:12
  • @cyrix no I can't. I want to save all answers and time spend on a Mcq when the user close the page, to prevent cheating on time. @ RahulSingh thanks for the link, I already found this post and it's likely what I'm doing.. – Mattew Eon Aug 01 '17 at 09:15
  • The only option would be to try a sync http call via xhr as stated in this comment: https://stackoverflow.com/a/39005933/7497763 – cyr_x Aug 01 '17 at 09:17
  • I tried with XHR too but it doesn't works. When I close the tab, nothing happen – Mattew Eon Aug 01 '17 at 09:51
  • I had a "No Accept-content-origin" error like, I fixed it in my Backend. Now there is no errors, but nothing either – Mattew Eon Aug 01 '17 at 09:57
  • I just added a console.log() on my canDeactivate() function, i can see the log, but the datas are not saved when I close the tab. But they are on refreshing it (btw I added the xhr part to my post) – Mattew Eon Aug 01 '17 at 10:01
  • @MattewEon check if you have the data when you close the browser – Rahul Singh Aug 01 '17 at 10:04
  • The browser have correct datas, but I put a System.out.println in my backend, the request never reached him when the tab close – Mattew Eon Aug 01 '17 at 10:17
  • @MattewEon i told you its quite difficult and a browser limitation a work around might be to save in local storage and then do something – Rahul Singh Aug 01 '17 at 10:21
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/150711/discussion-between-mattew-eon-and-rahul-singh). – Mattew Eon Aug 01 '17 at 10:25