Text-mask: Automatically enter decimal for CreateNumberMask add-on?

Created on 13 Feb 2018  路  3Comments  路  Source: text-mask/text-mask

I'm wondering if it's possible to add the ability to have the decimal place auto-entered as an option?

Similar to how some ATM's work when inputing amounts, the decimal is automatically assumed and each numeric input creates the number from the right.
For example, to input $20.00, one must enter 2, followed by three zeros only (no need to manually enter the decimal):

$__.__
$__._2
$__.20
$_2.00
$20.00

Most helpful comment

Here is something that seems to work, although the code is pretty ugly...
https://stackblitz.com/edit/react-wc4dj8

$__._1
$__.12
$_1.23
$12.34
$123.45
import React, { Component } from 'react';
import { render } from 'react-dom';
import MaskedInput from 'react-text-mask';

const maskFn = (input) => {
  var digits = input.split("").filter((c) => c >= '0' && c <= '9');
  if (digits.length < 4) {
    return ['$', /\d/, /\d/, '.', /\d/, /\d/];
  }

  var mask = [];
  for (var i = digits.length - 1; i >= 0; i--) {
    mask.push(/\d/);
    if (i == digits.length - 2) {
      mask.push('.');
    }
  }
  mask.push('$');
  return mask.reverse()
}

const pipe = (conformedValue, config) => {
  console.log(conformedValue, config);
  const _ = config.placeholderChar;
  var digits = config.rawValue.split("").filter((c) => c >= '0' && c <= '9');  
  if (digits.length == 0) {
    return ``;
  }
  if (digits.length == 1) {
    console.log(1)
    return `$${_}${_}.${_}${digits[0]}`;
  }
  const cents = digits.slice(digits.length - 2).join('');
  if (digits.length == 2) {
    return `$${_}${_}.${cents}`;
  }
  const dollars = digits.slice(0, digits.length - 2).join('');
  if (digits.length == 3) {
    return `$${_}${dollars}.${cents}`    
  }
  if (digits.length > 3) {
    return `$${dollars}.${cents}`
  }
  return conformedValue
}

class App extends Component {
  constructor() {
    super();
  }

  render() {
    return (
      <div>
        <MaskedInput
          type="text"
          mask={maskFn}
          placeholder="$"
          keepCharPositions={false}
          pipe={pipe}
        />
      </div>
    );
  }
}

render(<App />, document.getElementById('root'));

All 3 comments

I started saying that I needed something similar to type times, but then I though I should give it a try. So here is something close:
https://stackblitz.com/edit/react-lycodu

Essentially, specify a mask function, instead of a simple mask array. It's not exactly as you (or I) wanted, especially when only 1 digit is typed, but it's close. It looks like:

$
$1     <- this is awkward, should be $0.01, not $1
$.12
$1.23
$12.34
$123.45

The thing is I don't know yet how to fill the mask from the right. I think that might be possible with a pipe (?)

What I was trying to do for durations:

__:__:__
__:__:_1
__:__:12
__:_1:24
__:12:40
_1:24:00

Here is something that seems to work, although the code is pretty ugly...
https://stackblitz.com/edit/react-wc4dj8

$__._1
$__.12
$_1.23
$12.34
$123.45
import React, { Component } from 'react';
import { render } from 'react-dom';
import MaskedInput from 'react-text-mask';

const maskFn = (input) => {
  var digits = input.split("").filter((c) => c >= '0' && c <= '9');
  if (digits.length < 4) {
    return ['$', /\d/, /\d/, '.', /\d/, /\d/];
  }

  var mask = [];
  for (var i = digits.length - 1; i >= 0; i--) {
    mask.push(/\d/);
    if (i == digits.length - 2) {
      mask.push('.');
    }
  }
  mask.push('$');
  return mask.reverse()
}

const pipe = (conformedValue, config) => {
  console.log(conformedValue, config);
  const _ = config.placeholderChar;
  var digits = config.rawValue.split("").filter((c) => c >= '0' && c <= '9');  
  if (digits.length == 0) {
    return ``;
  }
  if (digits.length == 1) {
    console.log(1)
    return `$${_}${_}.${_}${digits[0]}`;
  }
  const cents = digits.slice(digits.length - 2).join('');
  if (digits.length == 2) {
    return `$${_}${_}.${cents}`;
  }
  const dollars = digits.slice(0, digits.length - 2).join('');
  if (digits.length == 3) {
    return `$${_}${dollars}.${cents}`    
  }
  if (digits.length > 3) {
    return `$${dollars}.${cents}`
  }
  return conformedValue
}

class App extends Component {
  constructor() {
    super();
  }

  render() {
    return (
      <div>
        <MaskedInput
          type="text"
          mask={maskFn}
          placeholder="$"
          keepCharPositions={false}
          pipe={pipe}
        />
      </div>
    );
  }
}

render(<App />, document.getElementById('root'));

I see there's already an issue for the same request, from 2016: https://github.com/text-mask/text-mask/issues/263.

We could really, really use this feature :)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

LXensen picture LXensen  路  6Comments

KevinGruber picture KevinGruber  路  6Comments

jvbianchi picture jvbianchi  路  5Comments

gabrielamarques picture gabrielamarques  路  6Comments

GeometricProgress picture GeometricProgress  路  4Comments