5

通貨のように表示したい入力があります。小数点以下 2 桁のみを許可し、必要に応じてカンマを自動的に追加しながら数字のみを許可するようにします。基本的に、ユーザーが「12345」と入力すると、入力が自動的に「12,345.00」と表示されるようにします。「12,345」でも構いませんが、「12345.5」と入力すると、「12,345.50」と表示する必要があります。これを達成するためにパイプを使用しようとしていますが、通貨記号を表示したくないため、「数値」パイプを使用することにしました (入力の前にラベルとしてドル記号が既にあります)。

これが私のコードです:

<input [ngModel]="Amount | number: '1.2-2'" (ngModelChange)="updateAmount($event)" class="form-control" id="Amount" name="Amount" tabindex="4" type="number" autocomplete="off">

いくつか問題があります。

  1. 数値を入力すると、自動的に 10 進数と 2 つの 0 が末尾に追加されますが、これは問題ありませんが、その末尾にカーソルも追加されるため、「55」と入力すると、「55.00」ではなく「55.00」と表示されます。 、「5.01」と表示されます(5.005と解釈してから5.01に丸めると思います)。ユーザーが期待する結果を見ながら自然に入力できるように、カーソルが最後まで行かないようにするにはどうすればよいですか?
  2. このフィルターは、実際には入力を小数点以下 2 桁に制限していません。「1234」と入力すると、「1.00234」と表示されます。また、複数の小数点を追加することもできます。小数点以下 2 桁までに制限するにはどうすればよいですか?
  3. 間違った入力でこのパイプを壊すのは本当に簡単です。たとえば、ユーザーが文字を入力すると、コンソールに次のようなエラーが表示されます。

パイプ「DecimalPipe」の無効な引数「11.00a」

このエラーの後、フィルターは完全に機能しなくなります。

入力を に設定しtype="number"て 1234 と入力すると、値は 1,234 になりますが、入力が消えて、コンソールに次のメッセージが表示されます。

指定された値「1,234」は有効な数値ではありません。値は次の正規表現と一致する必要があります: -?(\d+|\d+.\d+|.\d+)([eE][-+]?\d+)?

JQuery Inputmask を使用すると、入力の制限/表示に関して必要な結果が得られますが、ngModel が壊れて値が空に設定されるため、誰かがそれを回避する方法を知らない限り、これはオプションではありません。

必要な結果を得るために、パイプに変更を加えることはできますか? どうすればこれを機能させることができますか?

4

1 に答える 1

3

入力をマスキングするための前述のインスピレーションを受けたディレクティブは次のとおりです: https://plnkr.co/edit/aBvO2F?p=preview

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

@Directive({
  selector: '[ngModel][decimal]',
  host: {
    '(ngModelChange)': 'onInputChange($event)'
  }
})
export class DecimalMask {
  constructor(public model: NgControl) {}

  onInputChange(event, backspace) {
    var valArray = event.toString().split('.') : [];
    for(var i = 0; i < valArray.length; ++i) {
      valArray[i] = valArray[i].replace(/\D/g, '');
    }

    var newVal: number;

    if(valArray.length === 0) {
      newVal = '';
    }
    else {
      let matches = valArray[0].match(/[0-9]{3}/mig);

      if(matches !== null && valArray[0].length > 3) {
        let commaGroups = Array.from(Array.from(valArray[0]).reverse().join('').match(/[0-9]{3}/mig).join()).reverse().join('');
        let replacement = valArray[0].replace(commaGroups.replace(/\D/g, ''), '');

        newVal = (replacement.length > 0 ? replacement + "," : "") + commaGroups;
      } else {
        newVal = valArray[0];
      }

      if(valArray.length > 1) {
        newVal += "." + valArray[1].substring(0,2);
      }
    }
    // set the new value
    this.model.valueAccessor.writeValue(newVal);
  }
}

入力要素は次のようになります。

<input decimal [(ngModel)]="Amount"
    class="form-control" id="Amount" name="Amount" tabindex="4" autocomplete="off">

最後の文字がアルファであるか、小数点以下の長さが 2 より大きいかどうかを確認します。

ngDoCheck() {
    console.log(this.Amount);
    if(this.Amount) {
      this.Amount = this.Amount.replace(/[A-Za-z]/g, '');
      if(this.Amount.indexOf('.') !== -1) {
        var arrayVals = this.Amount.split('.');
        this.Amount = arrayVals[0] + "." + arrayVals[1].slice(0,2);
      }
    }
  }
于 2016-10-31T20:37:30.253 に答える