Angular 2+货币掩码

时间:2018-03-06 20:42:20

标签: angular angular2-directives currency-formatting

我为Angular 2+尝试了几个货币面具,但我的要求并不适合他们所以我自己试图创建一个指令。这就是我需要的:

  1. 允许空值。将值保留为数字,而不是字符串。
  2. 在焦点上删除货币格式。关于模糊重新格式化。
  3. 从右到左输入数字(因此,对于$ 250.00,用户必须输入[2] - > 5 - > 0.(因此不能从小数点开始)
  4. 不允许用户键入任何数字和小数点分隔符。
  5. 文字右对齐
  6. 我完成了大部分工作。

    唯一的问题是它只适用于focus / blur / keypress。由于数据是为我的组件加载的,因此指令中没有事件被触发,因此现有美元金额的初始加载不是格式化的。到目前为止,这是我的指令:

    import { Directive, ElementRef, HostListener, Input, AfterViewInit } from '@angular/core';
    import { CurrencyMaskService } from './currency-mask.service';
    
    @Directive({
      selector: '[appCurrencyMask]'
    })
    export class CurrencyMaskDirective implements AfterViewInit {
      private el: HTMLInputElement;
      constructor(private elementRef: ElementRef, private currencyMaskService: CurrencyMaskService) {
        this.el = elementRef.nativeElement;
      }
    
      ngAfterViewInit() {
        this.el.style.textAlign = 'right';
      }
    
      // On Focus remove all non-digit or decimal separator values
      @HostListener('focus', ['$event.target.value'])
      onfocus(value) {
        this.el.value = this.currencyMaskService.parse(value);
      }
    
      // On Blur remove all symbols except last . and set to currency format
      @HostListener('blur', ['$event.target.value'])
      onBlur(value) {
        this.el.value = this.currencyMaskService.transform(value);
      }
    
      // On Blur remove all symbols except last . and set to currency format
      @HostListener('change', ['$event.target.value'])
      onChange(value) {
        this.el.value = this.currencyMaskService.transform(value);
      }
    
      // Prevent user to enter anything but digits and decimal separator
      @HostListener('keypress', ['$event'])
      onKeyPress(event) {
        const key = event.which || event.keyCode || 0;
        if (key !== 46 && key > 31 && (key < 48 || key > 57)) {
          event.preventDefault();
        }
      }
    }
    

1 个答案:

答案 0 :(得分:1)

Reddit r / Angular2社区能够帮助我找到答案:https://www.reddit.com/r/Angular2/comments/82oojo/angular_2_currency_mask/

我完全不知道如何通过使用ControlValueAccessor跟踪值本身,我能够完成我想要的任务。请参阅以下代码:

import { Directive, ElementRef, HostListener, AfterViewInit, Input, forwardRef } from '@angular/core';
import { CurrencyMaskService } from './currency-mask.service';
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';

const noop = () => {};

export const CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR: any = {
  provide: NG_VALUE_ACCESSOR,
  useExisting: forwardRef(() => CurrencyMaskDirective),
  multi: true
};

@Directive({
  selector: '[appCurrencyMask]',
  providers: [CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR]
})
export class CurrencyMaskDirective implements AfterViewInit, ControlValueAccessor {
  private el: HTMLInputElement;
  private innerValue: any = 0;
  constructor(private elementRef: ElementRef, private currencyMaskService: CurrencyMaskService) {
    this.el = elementRef.nativeElement;
  }

  // Placeholders for the callbacks which are later providesd
  // by the Control Value Accessor
  private onTouchedCallback: () => void = noop;
  private onChangeCallback: (a: any) => void = noop;

  // set getter
  get value(): any {
    return this.innerValue;
  }

  // set accessor including call the onchange callback
  set value(v: any) {
    if (v !== this.innerValue) {
      this.innerValue = v;
      this.onChangeCallback(v);
    }
  }

  // Set touched on blur
  // onBlur() {
  //   this.onTouchedCallback();
  // }

  // From ControlValueAccessor interface
  writeValue(value: any) {
    if (value !== this.innerValue) {
      this.el.value = this.currencyMaskService.transform(value);
      this.innerValue = value;
    }
  }

  // From ControlValueAccessor interface
  registerOnChange(fn: any) {
    this.onChangeCallback = fn;
  }

  // From ControlValueAccessor interface
  registerOnTouched(fn: any) {
    this.onTouchedCallback = fn;
  }

  ngAfterViewInit() {
    this.el.style.textAlign = 'right';
  }

  // On Focus remove all non-digit or decimal separator values
  @HostListener('focus', ['$event.target.value'])
  onfocus(value) {
    this.el.value = this.currencyMaskService.parse(value);
  }

  // On Blue remove all symbols except last . and set to currency format
  @HostListener('blur', ['$event.target.value'])
  onBlur(value) {
    this.onTouchedCallback();
    this.el.value = this.currencyMaskService.transform(value);
    this.onChangeCallback(this.currencyMaskService.parse(this.el.value));
  }

  // On Change remove all symbols except last . and set to currency format
  @HostListener('change', ['$event.target.value'])
  onChange(value) {
    this.el.value = this.currencyMaskService.transform(value);
    this.onChangeCallback(this.currencyMaskService.parse(this.el.value));
  }

  // Prevent user to enter anything but digits and decimal separator
  @HostListener('keypress', ['$event'])
  onKeyPress(event) {
    const key = event.which || event.keyCode || 0;
    if (key !== 46 && key > 31 && (key < 48 || key > 57)) {
      event.preventDefault();
    }
  }
}

*编辑: 以下是我最终使用的完整代码:https://github.com/LeoTanoue/ngx-currency-mask