Angular 8自定义货币蒙版

时间:2019-06-17 20:20:46

标签: regex angular typescript angular-reactive-forms

现在,我正在制定货币屏蔽指令,该指令应与角反应形式兼容。这是我的Stackblitz https://stackblitz.com/edit/angular-8-currency-directive-insert

在输入元素中,我希望当我输入1、2、3、4、5时,我会在控制台{currency:“ $ 1,234”}}中看到,因为掩码运行.substring(0, 4)但是我看到{currency:“ $ 1,2345”}。 我在输入元素中看到了正确的显示值$ 1,234。

如果我将.substring(0,4)更改为.substring(0,3),则当我期望它显示$ 1,234时,输入元素中的显示值将显示$ 1,23。控制台输出正确的{currency:“ $ 1,234”}

任何欢迎找到问题根源的建议!我已经做过一些变通的工作,涉及拆分成数组,检查,弹出末尾和联接之类的事情,但是这些修复并不理想。仍然欢迎任何建议!

感谢您的支持。

要关注的代码可在下面提供的currency.directive.ts中找到:

 onInputChange(event, backspace) {
    let newVal = event.replace(/\D/g, '');
    if (newVal.length === 0) {
      newVal = '';
    } else if (newVal.length <= 3) {
      newVal = newVal.replace(/^(\d{0,3})/, '$1');
    // } else if (newVal.length <= 4) {
    //   newVal = newVal.replace(/^(\d{0,1})(\d{0,3})/, '$1,$2');
    } else {
      newVal = newVal.substring(0, 4);
      newVal = newVal.replace(/^(\d{0,1})(\d{1,3})/, '$1,$2');
    }
    this.ngControl.valueAccessor.writeValue("$"+ newVal);
    // console.log(this.toNumber(newVal))
  }

2 个答案:

答案 0 :(得分:1)

Stackblitz https://stackblitz.com/edit/angular-8-currency-directive-insert-jdwx4b

货币自定义输入

import { Component, forwardRef } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';

@Component({
  selector: 'app-currency',
  template: '<input [(ngModel)]="value" (keyup)="setValue(value)">',
  styleUrls: ['./currency.component.scss'],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => CurrencyComponent),
      multi: true
    }
  ]
})
export class CurrencyComponent implements ControlValueAccessor {

  value;

  constructor() {
  }

  setValue(event) {
    let newVal = event.toString().replace(/\D/g, '');
    if (newVal.length === 0) {
      newVal = '';
    } else if (newVal.length <= 3) {
      newVal = newVal.replace(/^(\d{0,3})/, '$1');
    } else {
      newVal = newVal.substring(0, 4);
      newVal = newVal.replace(/^(\d{0,1})(\d{1,3})/, '$1,$2');
    }
    newVal = '$' + newVal;
    if (newVal) {
      this.value = newVal;
      setTimeout(() => {
        // sometimes it needs a tick, specially first time
        this.propagateChange(this.value);
      });
    }
  }

  writeValue(value: any) {
    if (value !== undefined) {
      this.setValue(value);
    }
  }

  registerOnChange(fn) {
    this.propagateChange = fn;
  }

  registerOnTouched() {
  }

  propagateChange = (_: any) => {
  }

}

用法

<app-currency formControlName="currency"></app-currency>

答案 1 :(得分:1)

您的问题启发了我创建一个我将使用的CurrencyDirective。它不能像您现有的方法那样使用,但是我相信它可以代替或希望用来帮助其他人。

StackBlitz - Currency Format Directive

原因:

  • 我们不应将货币符号放在我们的值$1,234
  • 我们应该按照用户类型(无痛UX)格式化
  • 我们应该将货币值另存为原始数字(条 格式)
  • 我们不应将3个字符,4个字符,5个字符等进行正则表达式以有条件地添加格式(逗号或点)

这就是我所做的。 我处理pasteinputdrop事件,但是格式化是在getCurrencyFormat()内完成的:

getCurrencyFormat(val) {
    // 1. test for non-number characters and replace/remove them
    const filtered = parseInt(String(val).replace(this.currencyChars, ''));

    // 2. format the number (add commas)
    const usd = this.decimalPipe.transform(filtered, '1.0');

    // 3. replace the input value with formatted numbers
    this.renderer.setProperty(this.el.nativeElement, 'value', usd);
}

我认为保存货币应该以原始数字完成。所以在表单提交上,我这样做:

Number(this.form.get('currency').value.replace(/[^0-9]g/, ''));