Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

blur event not firing on angular component

I am trying to get a reactive form to properly handle blur events and it doesn't seem to react properly to blur.

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

@Component({
  selector: 'app-combo-box-basic',
  templateUrl: './combo-box-basic.html'
})
export class ComboBoxBasic {

  @HostListener('blur', ['$event.target']) onBlur(target) {
    console.log(`onBlur(): ${new Date()} - ${JSON.stringify(target)}`);
  }
}
<div class="btn-group mr-3">
  <input (blur)="onBlur($event.target)" type="text" class="btn btn-outline-success">
  <div class="btn-group" ngbDropdown role="group" aria-label="Button group with nested dropdown">
    <button (blur)="onBlur($event.target)" class="btn btn-outline-primary" ngbDropdownToggle></button>
    <div class="dropdown-menu" ngbDropdownMenu>
      <button class="dropdown-item">One</button>
      <button class="dropdown-item">Two</button>
      <button class="dropdown-item">Four!</button>
    </div>
  </div>
</div>
like image 544
RonnBlack Avatar asked Sep 05 '18 04:09

RonnBlack


2 Answers

blur event does not fire on controls in formarray

The same problem i.e. blur event not firing, and the same solution as suggested by @ronnblack, in a different situation albeit: In my case, blur event was not firing under a formarray. blur event fired in development mode though, however in production build, blur event is not firing in input and select, did not check on others. Solution is the same, set tabindex="0" for containing div for formarray, and the event started firing. Just in case, if someone faces the same situation.

like image 24
viking Avatar answered Sep 17 '22 12:09

viking


After a lot of searching and experimentation I found a number of items that were needed to get it work properly. A fully functional demo can be found here

  1. The Outer element must have: tabindex="0" so that it is focusable. This is achieved with: @HostBinding('attr.tabindex') tabindex = '0';

  2. Adding a HostListener for blur events will catch outer component: @HostListener('blur', ['$event.target']) onBlur(target) { ... }

  3. You still need to catch the blur events for the inner components so that clicking in and out will still fire. (blur)="onBlur($event.target)"

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

@Component({
  selector: 'app-combo-box-basic',
  templateUrl: './combo-box-basic.html'
})
export class ComboBoxBasic {

  // Make sure container can receive focus or else blur events won't be seen.
  @HostBinding('attr.tabindex') tabindex = '0';
  @HostListener('blur', ['$event.target']) onBlur(target) {
    console.log(`onBlur(): ${new Date()} - ${JSON.stringify(target)}`);
  }
}
<div class="btn-group mr-3">
  <input (blur)="onBlur($event.target)" type="text" class="btn btn-outline-success">
  <div class="btn-group" ngbDropdown role="group" aria-label="Button group with nested dropdown">
    <button (blur)="onBlur($event.target)" class="btn btn-outline-primary" ngbDropdownToggle></button>
    <div class="dropdown-menu" ngbDropdownMenu>
      <button class="dropdown-item">One</button>
      <button class="dropdown-item">Two</button>
      <button class="dropdown-item">Four!</button>
    </div>
  </div>
</div>
like image 163
RonnBlack Avatar answered Sep 20 '22 12:09

RonnBlack