diff --git a/web/client/components/I18N/IntlNumberFormControl.jsx b/web/client/components/I18N/IntlNumberFormControl.jsx index f69054c9ba..ffce0bfe78 100644 --- a/web/client/components/I18N/IntlNumberFormControl.jsx +++ b/web/client/components/I18N/IntlNumberFormControl.jsx @@ -128,6 +128,7 @@ class IntlNumberFormControl extends React.Component { }} componentClass={"input"} className="form-control intl-numeric" + locale={this.context && this.context.intl && this.context.intl.locale || "en-US"} /> ); } diff --git a/web/client/components/I18N/__tests__/IntlNumberFormatControl-test.jsx b/web/client/components/I18N/__tests__/IntlNumberFormatControl-test.jsx index b0e94a820b..5075959141 100644 --- a/web/client/components/I18N/__tests__/IntlNumberFormatControl-test.jsx +++ b/web/client/components/I18N/__tests__/IntlNumberFormatControl-test.jsx @@ -120,7 +120,7 @@ describe('IntlNumberFormControl', () => { TestUtils.Simulate.change(element, {target: {value: '12.'}}); expect(element.value).toBe("12"); TestUtils.Simulate.change(element, {target: {value: '12.0'}}); - expect(element.value).toBe("12"); + expect(element.value).toBe("12.0"); TestUtils.Simulate.change(element, {target: {value: '12.04'}}); expect(element.value).toBe("12.04"); TestUtils.Simulate.change(element, {target: {value: '12.402'}}); @@ -128,9 +128,9 @@ describe('IntlNumberFormControl', () => { TestUtils.Simulate.change(element, {target: {value: '-12.04'}}); expect(element.value).toBe("-12.04"); TestUtils.Simulate.change(element, {target: {value: '-12.40'}}); - expect(element.value).toBe("-12.4"); + expect(element.value).toBe("-12.40"); TestUtils.Simulate.change(element, {target: {value: '-12.0'}}); - expect(element.value).toBe("-12"); + expect(element.value).toBe("-12.0"); }); it('check calling passed onkeydown, onkeyup events', () => { const intl = {locale: "en-US"}; diff --git a/web/client/libs/numeric-input/NumericInput.jsx b/web/client/libs/numeric-input/NumericInput.jsx index a1226d46d9..48da517890 100644 --- a/web/client/libs/numeric-input/NumericInput.jsx +++ b/web/client/libs/numeric-input/NumericInput.jsx @@ -96,6 +96,7 @@ class NumericInput extends Component { defaultValue: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), strict: PropTypes.bool, componentClass: PropTypes.string, + locale: PropTypes.string, // eslint-disable-next-line consistent-return mobile(props, propName) { let prop = props[propName]; @@ -406,9 +407,15 @@ class NumericInput extends Component { ); let loose = !this._isStrict && (this._inputFocus || !this._isMounted); - - // incomplete number - if (loose && RE_INCOMPLETE_NUMBER.test(stringValue)) { + // create regex for numbers that contains centesimal decimal numbers + const numFormat = new Intl.NumberFormat(this.props.locale || "en-US"); + const parts = numFormat.formatToParts(12345.6); + const decimalSymbol = parts.find(d => d.type === "decimal").value; + const escapedDecimalSymbol = decimalSymbol.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + const RE_TRAILING_DECIMAL_ZEROS = new RegExp(`\\d+${escapedDecimalSymbol}\\d*0+`); + + // incomplete number or number contains decimal symbol [centesimal decimal numbers] + if ((loose && RE_INCOMPLETE_NUMBER.test(stringValue)) || RE_TRAILING_DECIMAL_ZEROS.test(stringValue)) { attrs.input.value = stringValue; } else if (loose && stringValue && !RE_NUMBER.test(stringValue)) {// Not a number and not empty (loose mode only) attrs.input.value = stringValue;