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>
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.
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
The Outer element must have: tabindex="0" so that it is focusable. This is achieved with: @HostBinding('attr.tabindex') tabindex = '0';
Adding a HostListener for blur events will catch outer component: @HostListener('blur', ['$event.target']) onBlur(target) { ... }
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With