in Angular2 how to know when ANY form input field lost focus

Why not use focusout it bubbles by default in the DOM

Here's a simple directive that catches focusout and checks if input value is blank, then sets value to zero:

@Directive({
  selector: '[blankToZero]'
})
export class BlankToZeroDirective {
  constructor(private elementHost: ElementRef) { }

  @HostListener('focusout')
  ensureInput(): void {
    if (Util.isNullOrEmpty(this.elementHost.nativeElement.value)) {
      this.elementHost.nativeElement.value = 0;
    }
  }
}

The blur event doesn't bubble, therefore we need to listen on every input element directly. Angular provides a nice solution for this situation.

A directive that applies to all input elements inside your template.

This directive uses a host-listener to listen for the blur events on all elements where the selector applies and forwards a bubbling input-blur event:

@Directive({
  selector: 'input,select',
  host: {'(blur)': 'onBlur($event)'}
})
class BlurForwarder {
  constructor(private elRef:ElementRef, private renderer:Renderer) {}

  onBlur($event) {
    this.renderer.invokeElementMethod(this.elRef.nativeElement, 
        'dispatchEvent', 
        [new CustomEvent('input-blur', { bubbles: true })]);
    // or just 
    // el.dispatchEvent(new CustomEvent('input-blur', { bubbles: true }));
    // if you don't care about webworker compatibility
  }
}

By adding the BlurForwarder directive to directives: [...] it will be applied to all elements in its template that match the selector.
The host-listener listens for bubbling input-blur events and calls our event handler:

@Component({
  selector: 'my-component',
  directives: [BlurForwarder],
  host: {'(input-blur)':'onInputBlur($event)'},
  template: `
<form>
  <input type="text" [(ngModel)]="xxx">
  <input type="text" [(ngModel)]="yyy">
  <input type="text" [(ngModel)]="zzz">
</form>`
}) {
  onInputBlur(event) {
    doSomething();
  }
}

Tags:

Angular