2

I want to set an onblur event handler in my Angular 9 app for when someone leaves the page. My page in question is mapped to a single component that has this ...

export class HotComponent implements OnInit {
  ...

  onBlur(): void {
    console.log("on blur called !!!");
  }

In the template, I set this ...

<div (blur)="onBlur()">
  <div>
    ...
  </div>
</div>

But when I navigate away from the browser window where this page is loaded and come back, I notice the onblur handler hasn't been called. What's the proper way to implement the onblur event handler for a page in Angular 9?

luiscla27
  • 4,956
  • 37
  • 49
satish
  • 703
  • 5
  • 23
  • 52
  • A div by default doesn't even receive focus, thus `blur` is going to be useless. See [this](https://stackoverflow.com/questions/18504139/div-onblur-function) for more information. I think you might be looking for `window.onbeforeunload`. See [this](https://stackoverflow.com/questions/15925251/trigger-an-event-when-user-navigates-away) for details. And the most upvoted answer about `HostListener` is exactly how you would watch for this event. – Dean Feb 01 '21 at 19:44

4 Answers4

5

Angular has something called HostListener, you need to use it!

 /**
   * Blur
   * @param eventName 'focusout' is the key
   * @param arguments of type '$event'
   */
  @HostListener('focusout', ['$event'])
  onFocusout(event) {
    // your logic goes here
    console.log('on blur called'); // This will get printed on blur
  }
luiscla27
  • 4,956
  • 37
  • 49
Srikar Phani Kumar M
  • 1,069
  • 1
  • 3
  • 8
  • This seems to work when I click on a different tab in my browser, but when I switch to a different application (using Cmd + tab on a Mac), it is not called (at least on Firefox). – satish Jan 28 '21 at 03:17
  • When you use Cmd + tab, you need to understand that the browser gets the first instantiation not the tab in which you are working. Once that is done, you need to write your logic, if the browser is forefront then hostlistener will work, if the host itself is not in focus it wont work right? – Srikar Phani Kumar M Jan 28 '21 at 17:01
  • I'm not quite understanding. Where do I need to apply the code you supplied or what other code do I need to add to trigger the onblur event on hte page when someone navigates away using (for example) Cmd + tab? – satish Jan 29 '21 at 02:10
1

I suggest you look into the onbeforeunload event. The onblur event isn't really designed to support your usecase because it targets the state change of an element. What you're attempting to do is intercept a history change on the browser.

The onbeforeunload property of the WindowEventHandlers mixin is the EventHandler for processing beforeunload events. These events fire when a window is about to unload its resources. At this point, the document is still visible and the event is still cancelable.

As outlined by the other replies, you can add an event listener via Angular's @HostListener annotation:

@HostListener('window:beforeunload')
foo() {
  // Do something here
}
El-Mo
  • 370
  • 2
  • 13
0

Two Issues will fix your problem. Add tabindex="0" to your DIV then handle the events below

<!-- language: html -->
// 1
<div  (blur)="onBlur()">  // tabindex="0" gets inserted by HostBinding
// recommend you use an input vs. DIV when user is entering data

the second issue is because there are two events happening as a result of your navigation you need to handle both. For firefox look here for the eventname. Once you import HostListener & HostBinding

<!-- language: typescript -->
// 2
import { Component, HostListener, HostBinding } from '@angular/core';
  1. Handle the focus event both focus in and blur for exit
  2. Handle the blur event as you want

<!-- language: typescript -->
// 3              -- you should be good :)
export class HotComponent { 

focusOutFunction() {
 console.log('focusOutFunction called');
 .. your logic here
 }

focusFunction() {
 console.log('focusFunction called');
 ..
 }

blurFunction()
 {
  console.log('blur called');
  ..
 }

   // you dont need to manually add it to HTML if you do this.
   @HostBinding('attr.tabindex') tabindex = '0';
}

Another option 2: if you have want to handle focusOut

  <!-- language: html -->
  <input tabindex="0" type="text" (focusout)="onFocusOutEvent($event)" />

  // in your component explicitly handle the event 
  onFocusOutEvent(event: any){
    console.log(event.target.value);
  }

A simple working sample with the events working for me, Please see console log below pic... it works. Can you please disable all your plugins and try.

Picture with the console events clearly

Transformer
  • 6,963
  • 2
  • 26
  • 52
  • Regarding your first solution, I assume one of those "onFocus" functions should be named somethign else b/c you can't have two fucntisons named the same with the same signature. Anyway, I changed one to "onFocus2", but not only do they not get called when I Cmd+tab away from the browser and return, they don't get called, when I click on another tab and return to the original tab. (Testing on Mac Firefox) – satish Feb 01 '21 at 00:20
  • Thats correct, I wrote it to give you an idea on how to _capture_ and _distinguish_ the various events. – Transformer Feb 01 '21 at 03:23
  • I updated the sample for you, and added a working skeleton on stackblitz with the console to show you I can see the events. Please turn off your plugins and try again – Transformer Feb 01 '21 at 04:32
-1

onBlur and onFocus won't get applied on div directly

Anyway, to solve your issue you can just add an EventListener on visibilitychange in your app.component or any other component's constructor.

document.addEventListener("visibilitychange", () => {
  if (document.hidden) {
    console.log("Browser tab is on blur")
  } else {
    console.log("Browser tab is on focus")
  }
});
luiscla27
  • 4,956
  • 37
  • 49
Nav Kumar V
  • 320
  • 2
  • 10
  • I'm on Firefox, and this logic seems to work when I click on a different Firefox tab. But when I select another application and bring that application to the forefront of my desktop, the logic isn't getting called. – satish Jan 20 '21 at 18:05