50

I mean, I want to track when a user leaves the app, closing browser or tabs.

Components and Directives has a lifecycle hook called ngOnDestroy, which is called when the component is destroyed, but it can't catch when the user leaves the app

import { Component, OnInit } from '@angular/core';

@Component({
  moduleId: module.id,
  selector: 'app',
  templateUrl: 'app.component.html'
})
export class AppComponent implements OnDestroy {
  constructor() { }

  ngOnDestroy() {
      alert(`I'm leaving the app!`);
  }

}

If the user closes the browser, the alert is not executed.

Cœur
  • 37,241
  • 25
  • 195
  • 267
chamberin
  • 521
  • 1
  • 4
  • 6

2 Answers2

78

You can listen to the unload or beforeunload events like this:

export class AppComponent {
  @HostListener('window:unload', [ '$event' ])
  unloadHandler(event) {
    // ...
  }

  @HostListener('window:beforeunload', [ '$event' ])
  beforeUnloadHandler(event) {
    // ...
  }
}

See also

Use IDE breakpoints to verify triggers.

Ankush Madankar
  • 3,689
  • 4
  • 40
  • 74
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • 3
    it is possible to get only tab/browser close. – CTN Mar 20 '17 at 11:51
  • AFAIK there is only `unload` and `beforeunload`. There might be some tricks or hacks to get some more information, but I have no knowledge about. – Günter Zöchbauer Mar 20 '17 at 13:14
  • If you find any resource inform me. Thanks for quick response. :) – CTN Mar 21 '17 at 04:58
  • 11
    @GünterZöchbauer The above method is not working for me...i put an alert, but it is not triggering..angular version 2.4.10 – radio_head Jun 15 '17 at 16:19
  • 8
    The alert will never be showed.. since the dialog will be gone by that time. Put a breakpoint on the developer tools so you can see it being trigged. – jpgrassi Oct 02 '17 at 16:49
  • 3
    This event is also triggered on refreshing the page not only on closing tab. – Abdulwehab Mar 13 '20 at 07:07
  • If anyone is using `alert` just to verify then it won't work. Use only Visual Studio Code for debugging even develop tools breakpoint won't work. – Ankush Madankar Feb 21 '23 at 12:58
1

visibilitychange event is an alternative

export class AppComponent {
   
  @HostListener('document:visibilitychange', ['$event']) 
  visibilityChange($event: Event) {
    
    if (document.visibilityState === 'hidden') {
      console.log("document.visibilityState === 'hidden'")
    }
  }
}

MDN usage notes for visibilityState say (May 31, 2022) :

This event fires with a visibilityState of hidden when a user navigates to a new page, switches tabs, closes the tab, minimizes or closes the browser, or, on mobile, switches from the browser to a different app.

For Safari beforeunload event is also recommended at Chrome Developers Blog: Page Lifecycle API by Philip Walton (May 27, 2020 ):

Safari does not reliably fire the pagehide or visibilitychange events when closing a tab (webkit bugs: 151610 and 151234), so in Safari you may need to also listen to the beforeunload event in order to detect a change to the hidden state. But since the beforeunload event can be canceled, you need to wait until after the event has finished propagating to know if the state has changed to hidden.

jyrkim
  • 2,849
  • 1
  • 24
  • 33