Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HostListener onBlur and onFocus not getting fired in angular4

Tags:

angular

I have a written a directive in angular 4 that captures onFocus and onBlur. I can see that my directive gets initialized when the form is loaded but dont see the obBlur or Onfocus firing when i click the input control. Not sure what is wrong. I have set the ShortNumberFormatterDirective on the input element

directive

import { Directive, HostListener, ElementRef, OnInit } from "@angular/core"; 
//import { MyCurrencyPipe } from "./my-currency.pipe"; 


 @Directive({ selector: "[shortNumberFormatter]" }) 
 export class ShortNumberFormatterDirective implements OnInit { 


   private el: HTMLInputElement; 


   constructor( 
     private elementRef: ElementRef, 
    // private currencyPipe: MyCurrencyPipe 
   ) { 
     this.el = this.elementRef.nativeElement; 
   } 


   ngOnInit() { 
     //this.el.value = this.currencyPipe.transform(this.el.value); 
   } 


   @HostListener("focus", ["$event.target.value"]) 
   onFocus(value) { 
     //this.el.value = this.currencyPipe.parse(value); // opossite of transform 
   } 


   @HostListener("blur", ["$event.target.value"]) 
   onBlur(value) { 
     //this.el.value = this.currencyPipe.transform(value); 
   } 


 } 

html

 <tr *ngFor="let item of domicileInfo.taxAssesment.items; let last = last; let item_IDX = index">
            <td *ngIf="!last" >
                <click-input   [classNames]="{'has-warning': !isMinValid(item,item_IDX) }">
                    <!-- <input [(ngModel)]="item.minSize"  (ngModelChange)="modelChanged(item,item_IDX)" required min="0" max="999999999999999" numberFormat="shortNumberFormat:.0"> -->
                     <input [(ngModel)]="item.minSize" shortNumberFormatter required min="0" max="999999999999999" numberFormat="shortNumberFormat:.0"> 
                </click-input>
              </td>

              <td *ngIf="!last">
                  <click-input  [classNames]="{'has-warning': !isMaxValid(item,item_IDX) }">
                      <!-- <input [(ngModel)]="item.maxSize"  (ngModelChange)="modelChanged(item,item_IDX)" required min="0" max="999999999999999" numberFormat="shortNumberFormat:.0"> -->
                       <input [(ngModel)]="item.maxSize"   required min="0" max="999999999999999" numberFormat="shortNumberFormat:.0"> 
                  </click-input>
              </td>  
  </tr>

Updated code based on Thomas response. If you notice i have written a parse method. The problem that i am facing is , the values are not getting transformed on form initialization. I am seeing the actual number for e.g 20000000 on the screen instead of 20M. I have tried to initialize in the onInit event but the cntrl value seem to be null.

Directive

import { Directive, HostListener } from "@angular/core";
import { NgControl } from '@angular/forms';
import { ShortNumberFormatPipe } from '../pipes/shortNumberFormat/shortNumberFormat.pipe';

@Directive({ selector: "[shortNumberFormatter]" })
export class ShortNumberFormatterDirective {
    _shortNumberPipe = new ShortNumberFormatPipe();
    get ctrl() {
        return this.ngControl.control;
    }

    constructor(
        private ngControl: NgControl
    ) { }

    ngOnInit() {
        if (this.ctrl != null && this.ctrl.value !=null) {
            const x = this._shortNumberPipe.transform(this.ctrl.value);
            console.log(x);
            this.ctrl.setValue(x);
        }
    }


    @HostListener("focus")
    onFocus() {
        const x = this._shortNumberPipe.parse(this.ctrl.value);
        console.log(x);
        this.ctrl.setValue(x);
    }

    @HostListener("blur")
    onBlur() {
        const x = this._shortNumberPipe.transform(this.ctrl.value);
        console.log(x);
        this.ctrl.setValue(x);
    }

} 

Pipe

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'shortNumberFormat'
})
export class ShortNumberFormatPipe implements PipeTransform {

  transform(number: any, decimals = 0) {

    if (number === null) {
      return;
    }

    number = parseFloat(number);

    if (isNaN(number)) {
      return;
    }

    if (isNaN(decimals)) {
      return;
    }

    const signPrefix = number < 0 ? '-' : '';
    number = Math.abs(number);

    if (number <= 999) { // hundreds
      number = number.toFixed(decimals);
    } else if (number >= 1000 && number <= 999999) {  // thousands
      number = (number / 1000).toFixed(decimals) + 'K';
    } else if (number >= 1000000 && number <= 999999999) { // millions
      number = (number / 1000000).toFixed(decimals) + 'M';
    } else { // billions
      number = (number / 1000000000).toFixed(decimals) + 'B';
    }

    return signPrefix + number;
  }

  parse(inputField: string)
  {
    let parsedNumber: any;

    if(inputField === '')
      return;

    let shortFormatCharector =  inputField.substr(inputField.length - 1);

    switch(shortFormatCharector)
    {
       case'k': 
      parsedNumber = parsedNumber * 1000;
      break; 
    case'M': 
      parsedNumber = parsedNumber * 1000000; 
      break; 
    case'B': 
      parsedNumber = parsedNumber * 1000000000; 
      break; 
    }
    return parsedNumber;
  }
}
like image 904
Tom Avatar asked Apr 17 '18 09:04

Tom


People also ask

Can we use HostListener in component?

Introduction. @HostBinding and @HostListener are two decorators in Angular that can be really useful in custom directives. @HostBinding lets you set properties on the element or component that hosts the directive, and @HostListener lets you listen for events on the host element or component.

What is HostListener in angular with example?

HostListenerlinkDecorator that declares a DOM event to listen for, and provides a handler method to run when that event occurs.

What are the HostListener events in angular?

@HostListener is Angular's decorator method that's used for listening to DOM events on the host element of both component and attribute directives. @HostListener sets the listeners once the directive is initialized and removes them automatically once the directive gets destroyed.


1 Answers

While there is a (blur) output event in Angular components, AFAIK the corresponding event of host listening is not blur but focusout. So you should rather use:

@HostListener("focusout", ["$event.target.value"]) 
onBlur(value) { 
  // ...
} 
like image 58
Javarome Avatar answered Oct 17 '22 07:10

Javarome