diff --git a/packages/zent/__tests__/number-input.spec.jsx b/packages/zent/__tests__/number-input.spec.jsx index 8334d30780..4c050d5f5d 100644 --- a/packages/zent/__tests__/number-input.spec.jsx +++ b/packages/zent/__tests__/number-input.spec.jsx @@ -48,6 +48,19 @@ describe('NumberInput', () => { expect(wrapper.state('value').cmp(new Decimal(0))).toBe(0); }); + it('dynamic decimal point precision', () => { + const wrapper = mount( + + ); + expect(wrapper.state('input')).toBe('2.123'); + const input = wrapper.find('input'); + input.simulate('blur'); + input.instance().value = '4.1'; + input.simulate('change'); + input.simulate('blur'); + expect(wrapper.state('input')).toBe('4.1'); + }); + it('change value within min and max ', () => { let wrapper = mount(); wrapper.find('.zent-number-input-arrowup').simulate('click'); diff --git a/packages/zent/src/form/demos/2.builtin-field.md b/packages/zent/src/form/demos/2.builtin-field.md index 5e71de947c..30f850bf97 100644 --- a/packages/zent/src/form/demos/2.builtin-field.md +++ b/packages/zent/src/form/demos/2.builtin-field.md @@ -18,6 +18,7 @@ zh-CN: tagText2: 书籍 tagText3: 旅行 ageText: 年龄 + weight: 体重 colorText: 喜欢的颜色 dateRangeText: 身份证有效期 dateRangeValidationErrors: 请填写有效期 @@ -50,6 +51,7 @@ en-US: tagText2: Book tagText3: Travel ageText: Age + weight: Weight colorText: Favorite color dateRangeText: Validity period dateRangeValidationErrors: Please select the dateRange @@ -139,6 +141,15 @@ function Component() { showStepper: true, }} /> + void; decimal?: number; + dynamicDecimal?: boolean; onInput?: (value: string) => void; min?: number | string; } @@ -121,7 +122,14 @@ function getStateFromProps( max, delta: Decimals.getDelta(props.decimal, props.step), ...(updateValueInState - ? Decimals.normalizeValue(props.value, min, max, props.decimal) + ? Decimals.normalizeValue( + props.value, + min, + max, + props.decimal, + false, + props.dynamicDecimal + ) : {}), }; } @@ -136,6 +144,7 @@ export class NumberInput extends Component< type: 'number', decimal: 0, size: 'normal', + dynamicDecimal: false, }; static contextType = DisabledContext; @@ -218,14 +227,15 @@ export class NumberInput extends Component< const { onBlur } = this.props; onBlur?.(e); } else { - const { onChange, decimal, showTooltip } = this.props; + const { onChange, decimal, showTooltip, dynamicDecimal } = this.props; const { input, min, max } = this.state as INumberInputDecimalState; const normalized = Decimals.normalizeValue( input, min, max, decimal, - showTooltip + showTooltip, + dynamicDecimal ); onChange?.(normalized.input); this.setState(normalized, () => { @@ -363,7 +373,9 @@ export class NumberInput extends Component< props.value, nextState.min, nextState.max, - props.decimal + props.decimal, + false, + props.dynamicDecimal ); nextState.value = value; nextState.input = input; diff --git a/packages/zent/src/number-input/README_en-US.md b/packages/zent/src/number-input/README_en-US.md index a97a7c2d0c..6a01fbf187 100644 --- a/packages/zent/src/number-input/README_en-US.md +++ b/packages/zent/src/number-input/README_en-US.md @@ -26,6 +26,7 @@ Default value type is string. Under integer mode, value type is number, with def | integer | Integer mode | `boolean` | `false` | | No | | decimal | Decimal | `number` | `0` | | No | | step | Step used in stepper | `number` | | | No | +| dynamicDecimal | show decimal as input | `boolean` | `false` | | No | | min | Minimum value in the range | `number` | | | No | | max | Maximum value in the range | `number` | | | No | | placeholder | Placeholder text | `string` | `''` | | No | diff --git a/packages/zent/src/number-input/README_zh-CN.md b/packages/zent/src/number-input/README_zh-CN.md index f9d3200a0d..edc1fcdbdf 100644 --- a/packages/zent/src/number-input/README_zh-CN.md +++ b/packages/zent/src/number-input/README_zh-CN.md @@ -27,6 +27,7 @@ group: 信息录入 | integer | 整数模式 | `boolean` | `false` | | 否 | | decimal | 数值精度 | `number` | `0` | | 否 | | step | 步进 | `number` | 整数模式为 `1`,小数模式根据精度而定 | | 否 | +| dynamicDecimal | 是否完整保存用户输入的小数位数 | `boolean` | `false` | | 否 | | min | 数值范围最小值 | `number` | | | 否 | | max | 数值范围最大值 | `number` | | | 否 | | placeholder | 原生 placeholder 文案 | `string` | `''` | | 否 | diff --git a/packages/zent/src/number-input/decimal.ts b/packages/zent/src/number-input/decimal.ts index e4d7625091..de7ba60be9 100644 --- a/packages/zent/src/number-input/decimal.ts +++ b/packages/zent/src/number-input/decimal.ts @@ -20,6 +20,18 @@ export function getDelta(decimal: number, step?: number): Decimal { return new Decimal(1).div(Math.pow(10, decimal)); } +/** + * 取小数点后数字长度 + * @param decimal + * @example (3.12) => 2 + */ +function getDecimalsLength(decimal: Decimal) { + const DecimalsRegexMatch = /\.(\d*)$/.exec(decimal.toString()); + if (DecimalsRegexMatch) { + return DecimalsRegexMatch[1].length; + } + return 0; +} function fromPotential(v: number | string | undefined): Decimal | null { v = String(v); if (isDecimal(v)) { @@ -42,7 +54,8 @@ export function normalizeValue( min: Decimal | null, max: Decimal | null, decimalPlaces: number, - showTooltip?: boolean + showTooltip?: boolean, + dynamicDecimal?: boolean ): { input: string; value: Decimal; @@ -93,7 +106,9 @@ export function normalizeValue( } const popState = pop && showTooltip ? { pop } : {}; return { - input: decimal.toFixed(decimalPlaces), + input: decimal.toFixed( + dynamicDecimal ? getDecimalsLength(decimal) : decimalPlaces + ), value: decimal, ...popState, }; diff --git a/packages/zent/src/number-input/demos/2.decimal-point.md b/packages/zent/src/number-input/demos/2.decimal-point.md index 3600016188..261607e0f7 100644 --- a/packages/zent/src/number-input/demos/2.decimal-point.md +++ b/packages/zent/src/number-input/demos/2.decimal-point.md @@ -22,6 +22,7 @@ ReactDOM.render( step={1} placeholder="{i18n.placehoder}" /> + , mountNode );