38

I am working on a chat application using angular 2.

How can i send the finish chat command to the backend when the user closes the window?

My component has a method that calls the backend service to end the chat in the following way

 endChat() {
        this.chatService.endChat(this.chatSessionInfo).subscribe(
            result => this.OnGetMessages(result),
            error => this.OnChatEndError(error)
        );
    }

How can i execute that code when closing the window? How can i detect the window close event?

I tried with ngOnDestroy but for some reason the code is not being executed.

In my Component.ts I have.

import { Component, OnInit, AfterViewChecked, ElementRef, ViewChild,OnDestroy} from '@angular/core';

export class ChatComponent implements OnInit, AfterViewChecked,OnDestroy  {

and finally

 ngOnDestroy() { 
    this.endChat();
 }

Thanks!

federom
  • 1,145
  • 2
  • 9
  • 11
  • Have you implemented the backend with socket.io? – Maximilian Riegler Aug 17 '16 at 14:51
  • No, i am using WebApi 2 – federom Aug 17 '16 at 15:10
  • I don't know how you wired up your chat in the background, but I'd suggest using [`SignalR`](http://www.asp.net/signalr) for something like a chat. On disconnect there will be [fired an event](http://www.asp.net/signalr/overview/guide-to-the-api/handling-connection-lifetime-events) on the server. Have a look here for an example: https://github.com/FabianGosebrink/ASPNET-Core-Angular2-SignalR-Typescript – Maximilian Riegler Aug 17 '16 at 15:17
  • use jquery for that check this answer http://stackoverflow.com/questions/1631959/how-to-capture-the-browser-window-close-event – rashfmnb Aug 17 '16 at 15:18
  • @rinukkusu I am using socket.io. Do you have a socket.io specific solution for this? – Marc Borni May 18 '17 at 08:10
  • @MarcBorni No, I'd go with Günter's answer! BUT if you just need to execute some code on your backend, then there is the [`'disconnect'` event](http://stackoverflow.com/questions/17287330/socket-io-handling-disconnect-event). – Maximilian Riegler May 18 '17 at 09:32

3 Answers3

68

Thanks everyone for the help. I was able to create a solution based on different proposal.

First I used the beforeunload event in the component

@HostListener('window:beforeunload', ['$event'])
beforeunloadHandler(event) {
    this.endChat();
}

where

endChat() {
    this.chatService.endChatSync(this.chatSessionInfo);
}

Then, the trick is to make the http call sync not async.

Before, the endchat method at the chat service was

    endChat(chatSessionInfo: ChatSessionInfo)  : Observable<ChatTranscription> {
    console.log("Ending chat..");
    let body = JSON.stringify(chatSessionInfo);
    let headers = new Headers({ 'Content-Type': 'application/json' });
    let options = new RequestOptions({ headers: headers });
    return this.http.delete(this.apiUrl + "Chat?userId="+chatSessionInfo.UserId+"&secureKey="+chatSessionInfo.SecureKey,options)
             .map(this.extractData)
            .catch(this.handleError);
}

I was able to make it work with

endChatSync(chatSessionInfo: ChatSessionInfo)  {
    console.log("Ending chat..");
     let xhr = new XMLHttpRequest()
     xhr.open("DELETE",this.apiUrl +"Chat?userId="+chatSessionInfo.UserId+"&secureKey="+chatSessionInfo.SecureKey,false);
     xhr.send();
}

Hope this helps!

federom
  • 1,145
  • 2
  • 9
  • 11
23
@HostListener('window:unload', ['$event'])
unloadHandler(event) {
  ...
}

See also javascript to check when the browser window is close

Community
  • 1
  • 1
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • Does this have a timeout or does it block until the handler finishes? – Maximilian Riegler Aug 17 '16 at 15:19
  • 1
    See https://developer.mozilla.org/de/docs/Web/API/WindowEventHandlers/onunload, https://developer.mozilla.org/de/docs/Web/Events/beforeunload. I haven't used them myself for a while and don't remember details. – Günter Zöchbauer Aug 17 '16 at 15:22
  • 1
    The issue in that case is that the window get closed before the service call is sent.. – federom Aug 17 '16 at 19:29
  • I know thos is tricky but there is nothing Angular can do about it. That's a browser limitation. – Günter Zöchbauer Aug 17 '16 at 19:32
  • @GünterZöchbauer Where should i have to write this code? – Pinank Lakhani Dec 14 '16 at 10:57
  • 3
    `@HostListener('window:unload', ['$event'])` didn't work for me (Angular2 v2.4.6) to show the confirmation dialog by setting the `e.returnValue`. What did was `@HostListener('window:beforeunload', ['$event'])`, however. – Vilinkameni May 02 '17 at 16:49
  • Take a look at my previous post. That works for Angular 2 – federom May 19 '17 at 19:37
  • @GünterZöchbauer could you help me to solve this https://stackoverflow.com/questions/50266974/how-to-call-the-api-before-closing-the-browser-window-in-angular4 – Nikson May 10 '18 at 06:53
  • I used unloadHandler and beforeUnloadHandler.. sometimes it does logging and sometimes it misses it.. I need log everytime when app is closed... – Ziggler Jun 27 '18 at 17:22
2

Chrome now disallows synchronous XHR during page dismissal when the page is being navigated away from or closed by the user.

https://www.chromestatus.com/feature/4664843055398912

so now what to do to make synchronous calls on this event.