Angular 2+货币蒙版 [英] Angular 2+ Currency Mask

查看:83
本文介绍了Angular 2+货币蒙版的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我为Angular 2+尝试了几种货币屏蔽,但是我的要求并不完全适合他们,因此我尝试自己创建一个指令.这就是我需要的:

I tried a couple of the currency masks out there for Angular 2+ but my requirements don't really fit them so I'm trying to create a Directive myself. Here's what I need:

  1. 允许使用空值.将值保留为数字,而不是字符串.
  2. 聚焦时删除货币格式.在模糊时重新格式化.
  3. 从右至左输入数字(因此,对于$ 250.00,用户必须键入[2]-> 5->0.(因此不能从小数点开始)
  4. 除数字和小数点分隔符外,不允许用户输入其他任何内容.
  5. 右对齐文本

我完成了大部分工作.

I got most of this working.

唯一的问题是它仅适用于焦点/模糊/按键.由于数据是为我的组件异步加载的,因此指令中不会触发任何事件,因此不会格式化现有美元金额的初始负荷.到目前为止,这是我的指令:

The only issue is that it only works on focus/blur/keypress. Since the data is loaded async for my components, no event in the directive is triggered so the initial load of existing dollar amounts isn't formatted. Here's my Directive so far:

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

推荐答案

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

The Reddit r/Angular2 community was able to help me find the answer: https://www.reddit.com/r/Angular2/comments/82oojo/angular_2_currency_mask/

我完全不知道如何使用ControlValueAccessor来跟踪值本身,因此我能够完成我想要的事情.参见下面的代码:

I was completely missing on how to keep track of the value itself, by using the ControlValueAccessor I was able to accomplish what I wanted. See code below:

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 -遮罩

* Here's the full code I ended up using: https://github.com/LeoTanoue/ngx-currency-mask

这篇关于Angular 2+货币蒙版的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆