ngx-mask icon indicating copy to clipboard operation
ngx-mask copied to clipboard

Currency mask without need to type decimal separator

Open pedrollmatias opened this issue 4 years ago • 3 comments

Hi,

I'm trying to mask a value as brazilian currency. I want a mask which the user don't need to type the decimal separator (in my case, a comma) and the typed number is formatted to BRL currency automatically. For example:

Typed value > Masked value > Control value: 1 > R$ 0,01 > 0.01 10 > R$ 0,10 > 0.10 100 > R$ 1,00 > 1 123456 > R$ 1.234,56 > 1234.56

Actually, the pattern to get the control value according to typed value is a division by 100:

1 : 100 = 0.01 10 : 100 = 0.10 ...

The closest I got was

<input mask="separator.2" [thousandSeparator]="'.'" [decimalMarker]="','" prefix="R$ " />

but user must type the comma to have the decimal part.

Is possible to get this type of mask only with ngx-mask and without write some extra code?

pedrollmatias avatar Apr 24 '20 22:04 pedrollmatias

I've added the code below to the checkInputPrecision method in the mask-applier.service.ts file. I got the expected result for this proposed issue. However, the cursor in the input field is not stayed, and it's moved to before the decimal separator. I've used the "split" method because I don't have extensive knowledge of pattern method.

private checkInputPrecision = (
    inputValue: string,
    precision: number,
    decimalMarker: IConfig['decimalMarker'],
    beginByDecimal = false
  ): string => {
    if (precision < Infinity) {
      const precisionRegEx = new RegExp(this._charToRegExpExpression(decimalMarker) + `\\d{${precision}}.*$`);
      const precisionMatch = inputValue.match(precisionRegEx);

      if (beginByDecimal) {
        if (!precisionMatch) {
          const splited = inputValue.split(decimalMarker);
          const decimalLength = splited.length === 2 ? splited[1].length : 0;
          const diff = precision - decimalLength;
          if (diff > 0) {
            const integer = splited[0].length > diff ? splited[0].substring(0, splited[0].length - diff) : '';
            const toChange =
              splited[0].length > diff ? splited[0].substring(splited[0].length - diff, splited[0].length) : splited[0];
            const end = splited.length === 2 ? splited[1] : '';
            let decimal = toChange + end;
            decimal =
              precision - decimal.length > 0
                ? Array(precision - decimal.length)
                    .fill(0)
                    .join('') +
                  '' +
                  decimal
                : decimal;
            inputValue = integer + decimalMarker + decimal;
          }
        } else {
          const splited = inputValue.split(decimalMarker);
          const decimalLength = splited.length === 2 ? splited[1].length : 0;
          const diff = decimalLength - precision;
          if (diff > 0) {
            let integer = splited[0];
            const toChange = splited[1].substring(0, diff);
            const end = splited[1].substring(diff, splited[1].length);
            integer = integer + toChange;
            inputValue = integer + decimalMarker + end;
          }
        }
      } else {
        if (precisionMatch && precisionMatch[0].length - 1 > precision) {
          const diff = precisionMatch[0].length - 1 - precision;
          inputValue = inputValue.substring(0, inputValue.length - diff);
        }
        if (precision === 0 && inputValue.endsWith(decimalMarker)) {
          inputValue = inputValue.substring(0, inputValue.length - 1);
        }
      }
    }
    return inputValue;
  };

juninhocruzg3 avatar Nov 01 '20 23:11 juninhocruzg3

Pretty sad we have to use another projects just because ngx-mask does not care to solve this high requested problem.

d10n4t4n avatar Sep 24 '21 05:09 d10n4t4n

Would be very appreciated feature.

duwejeferson avatar Sep 05 '23 12:09 duwejeferson