HostListener onBlur和onFocus没有在angular4中被触发

时间:2018-04-17 09:36:36

标签: angular

我在角4中写了一个指令来捕获onFocus和onBlur。我可以看到我的指令在加载表单时被初始化但是当我点击输入控件时没有看到obBlur或Onfocus触发。不确定有什么问题。我在输入元素

上设置了ShortNumberFormatterDirective

指令

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>

根据Thomas的回复更新了代码。如果你注意到我写了一个解析方法。我面临的问题是,值不会在表单初始化时转换。我在屏幕上看到实际的数字,例如20000000,而不是20M。我试图在onInit事件中初始化,但cntrl值似乎为null。

指令

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);
    }

} 

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;
  }
}

2 个答案:

答案 0 :(得分:2)

如果您打算在<input>元素上使用此指令,我建议您注入NgControl元素,并直接操作FormControl。它比使用$event.target.value方法更清晰。

import { Directive, HostListener } from "@angular/core";
import { NgControl } from '@angular/forms';

@Directive({ selector: "[upperLower]" })
export class UpperLowerDirective {

  get ctrl() {
    return this.ngControl.control;
  }

  constructor(
    private ngControl: NgControl
  ) { }

  @HostListener("focus")
  onFocus() {
    this.ctrl.setValue(this.ctrl.value.toUpperCase());
  }

  @HostListener("blur")
  onBlur() {
    this.ctrl.setValue(this.ctrl.value.toLowerCase());
  }

} 

Live demo

答案 1 :(得分:1)

虽然Angular组件中有一个(blur)输出事件,但AFAIK主机监听的相应事件不是blur而是focusout。因此,您应该使用:

@HostListener("focusout", ["$event.target.value"]) 
onBlur(value) { 
  // ...
}