mirror of https://github.com/ElemeFE/element
InputNumber: add precision attribute (#11281)
parent
66f90b9e37
commit
bcfb1d3c71
|
@ -99,6 +99,31 @@ Allows you to define incremental steps.
|
||||||
```
|
```
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
### Precision
|
||||||
|
|
||||||
|
:::demo Add `precision` attribute to set the precision of input value.
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<el-input-number v-model="num9" :precision="2" :step="0.1" :max="10"></el-input-number>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
num9: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
The value of `precision` must be a positive integer and should not be less than the decimal places of `step`.
|
||||||
|
:::
|
||||||
|
|
||||||
### Size
|
### Size
|
||||||
|
|
||||||
Use attribute `size` to set additional sizes with `medium`, `small` or `mini`.
|
Use attribute `size` to set additional sizes with `medium`, `small` or `mini`.
|
||||||
|
@ -159,6 +184,7 @@ Use attribute `size` to set additional sizes with `medium`, `small` or `mini`.
|
||||||
|min | the minimum allowed value | number | — | `-Infinity` |
|
|min | the minimum allowed value | number | — | `-Infinity` |
|
||||||
|max | the maximum allowed value | number | — | `Infinity` |
|
|max | the maximum allowed value | number | — | `Infinity` |
|
||||||
|step | incremental step | number | — | 1 |
|
|step | incremental step | number | — | 1 |
|
||||||
|
|precision | precision of input value | number | — | — |
|
||||||
|size | size of the component | string | large/small| — |
|
|size | size of the component | string | large/small| — |
|
||||||
|disabled| whether the component is disabled | boolean | — | false |
|
|disabled| whether the component is disabled | boolean | — | false |
|
||||||
|controls| whether to enable the control buttons | boolean | — | true |
|
|controls| whether to enable the control buttons | boolean | — | true |
|
||||||
|
|
|
@ -99,6 +99,31 @@ Le permite definir el nivel de incremento de los saltos.
|
||||||
```
|
```
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
### Precision
|
||||||
|
|
||||||
|
:::demo Add `precision` attribute to set the precision of input value.
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<el-input-number v-model="num9" :precision="2" :step="0.1" :max="10"></el-input-number>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
num9: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
The value of `precision` must be a positive integer and should not be less than the decimal places of `step`.
|
||||||
|
:::
|
||||||
|
|
||||||
### Tamaño
|
### Tamaño
|
||||||
|
|
||||||
Utilice el atributo `size` para establecer tamaños adicionales con `medium`, `small` o `mini`.
|
Utilice el atributo `size` para establecer tamaños adicionales con `medium`, `small` o `mini`.
|
||||||
|
@ -160,6 +185,7 @@ Utilice el atributo `size` para establecer tamaños adicionales con `medium`, `s
|
||||||
| min | el valor mínimo permitido | number | — | `-Infinity` |
|
| min | el valor mínimo permitido | number | — | `-Infinity` |
|
||||||
| max | el valor maximo permitido | number | — | `Infinity` |
|
| max | el valor maximo permitido | number | — | `Infinity` |
|
||||||
| step | incremento (salto) | number | — | 1 |
|
| step | incremento (salto) | number | — | 1 |
|
||||||
|
| precision | precision of input value | number | — | — |
|
||||||
| size | tamaño del componente | string | large/small | — |
|
| size | tamaño del componente | string | large/small | — |
|
||||||
| disabled | si el componente esta deshabilitado | boolean | — | false |
|
| disabled | si el componente esta deshabilitado | boolean | — | false |
|
||||||
| controls | si se activan los botones de control | boolean | — | true |
|
| controls | si se activan los botones de control | boolean | — | true |
|
||||||
|
|
|
@ -9,7 +9,8 @@
|
||||||
num5: 1,
|
num5: 1,
|
||||||
num6: 1,
|
num6: 1,
|
||||||
num7: 1,
|
num7: 1,
|
||||||
num8: 1
|
num8: 1,
|
||||||
|
num9: 1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -97,6 +98,31 @@
|
||||||
```
|
```
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
### 精度
|
||||||
|
|
||||||
|
:::demo 设置 `precision` 属性可以控制数值精度,接收一个 `Number`。
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<el-input-number v-model="num9" :precision="2" :step="0.1" :max="10"></el-input-number>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
num9: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
`precision` 的值必须是一个正整数,并且不能小于 `step` 的小数位数。
|
||||||
|
:::
|
||||||
|
|
||||||
### 尺寸
|
### 尺寸
|
||||||
|
|
||||||
额外提供了 `medium`、`small`、`mini` 三种尺寸的数字输入框
|
额外提供了 `medium`、`small`、`mini` 三种尺寸的数字输入框
|
||||||
|
@ -156,6 +182,7 @@
|
||||||
| min | 设置计数器允许的最小值 | number | — | -Infinity |
|
| min | 设置计数器允许的最小值 | number | — | -Infinity |
|
||||||
| max | 设置计数器允许的最大值 | number | — | Infinity |
|
| max | 设置计数器允许的最大值 | number | — | Infinity |
|
||||||
| step | 计数器步长 | number | — | 1 |
|
| step | 计数器步长 | number | — | 1 |
|
||||||
|
| precision| 数值精度 | number | — | — |
|
||||||
| size | 计数器尺寸 | string | large, small | — |
|
| size | 计数器尺寸 | string | large, small | — |
|
||||||
| disabled | 是否禁用计数器 | boolean | — | false |
|
| disabled | 是否禁用计数器 | boolean | — | false |
|
||||||
| controls | 是否使用控制按钮 | boolean | — | true |
|
| controls | 是否使用控制按钮 | boolean | — | true |
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
</span>
|
</span>
|
||||||
<el-input
|
<el-input
|
||||||
ref="input"
|
ref="input"
|
||||||
:value="currentValue"
|
:value="currentInputValue"
|
||||||
:disabled="inputNumberDisabled"
|
:disabled="inputNumberDisabled"
|
||||||
:size="inputNumberSize"
|
:size="inputNumberSize"
|
||||||
:max="max"
|
:max="max"
|
||||||
|
@ -96,7 +96,13 @@
|
||||||
default: ''
|
default: ''
|
||||||
},
|
},
|
||||||
name: String,
|
name: String,
|
||||||
label: String
|
label: String,
|
||||||
|
precision: {
|
||||||
|
type: Number,
|
||||||
|
validator(val) {
|
||||||
|
return val >= 0 && val === parseInt(val, 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@ -108,7 +114,14 @@
|
||||||
immediate: true,
|
immediate: true,
|
||||||
handler(value) {
|
handler(value) {
|
||||||
let newVal = value === undefined ? value : Number(value);
|
let newVal = value === undefined ? value : Number(value);
|
||||||
if (newVal !== undefined && isNaN(newVal)) return;
|
if (newVal !== undefined) {
|
||||||
|
if (isNaN(newVal)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.precision !== undefined) {
|
||||||
|
newVal = this.toPrecision(newVal, this.precision);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (newVal >= this.max) newVal = this.max;
|
if (newVal >= this.max) newVal = this.max;
|
||||||
if (newVal <= this.min) newVal = this.min;
|
if (newVal <= this.min) newVal = this.min;
|
||||||
this.currentValue = newVal;
|
this.currentValue = newVal;
|
||||||
|
@ -123,9 +136,17 @@
|
||||||
maxDisabled() {
|
maxDisabled() {
|
||||||
return this._increase(this.value, this.step) > this.max;
|
return this._increase(this.value, this.step) > this.max;
|
||||||
},
|
},
|
||||||
precision() {
|
numPrecision() {
|
||||||
const { value, step, getPrecision } = this;
|
const { value, step, getPrecision, precision } = this;
|
||||||
return Math.max(getPrecision(value), getPrecision(step));
|
const stepPrecision = getPrecision(step);
|
||||||
|
if (precision !== undefined) {
|
||||||
|
if (stepPrecision > precision) {
|
||||||
|
console.warn('[Element Warn][InputNumber]precision should not be less than the decimal places of step');
|
||||||
|
}
|
||||||
|
return precision;
|
||||||
|
} else {
|
||||||
|
return Math.max(getPrecision(value), stepPrecision);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
controlsAtRight() {
|
controlsAtRight() {
|
||||||
return this.controlsPosition === 'right';
|
return this.controlsPosition === 'right';
|
||||||
|
@ -138,11 +159,19 @@
|
||||||
},
|
},
|
||||||
inputNumberDisabled() {
|
inputNumberDisabled() {
|
||||||
return this.disabled || (this.elForm || {}).disabled;
|
return this.disabled || (this.elForm || {}).disabled;
|
||||||
|
},
|
||||||
|
currentInputValue() {
|
||||||
|
const currentValue = this.currentValue;
|
||||||
|
if (typeof currentValue === 'number' && this.precision !== undefined) {
|
||||||
|
return currentValue.toFixed(this.precision);
|
||||||
|
} else {
|
||||||
|
return currentValue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
toPrecision(num, precision) {
|
toPrecision(num, precision) {
|
||||||
if (precision === undefined) precision = this.precision;
|
if (precision === undefined) precision = this.numPrecision;
|
||||||
return parseFloat(parseFloat(Number(num).toFixed(precision)));
|
return parseFloat(parseFloat(Number(num).toFixed(precision)));
|
||||||
},
|
},
|
||||||
getPrecision(value) {
|
getPrecision(value) {
|
||||||
|
@ -158,14 +187,14 @@
|
||||||
_increase(val, step) {
|
_increase(val, step) {
|
||||||
if (typeof val !== 'number' && val !== undefined) return this.currentValue;
|
if (typeof val !== 'number' && val !== undefined) return this.currentValue;
|
||||||
|
|
||||||
const precisionFactor = Math.pow(10, this.precision);
|
const precisionFactor = Math.pow(10, this.numPrecision);
|
||||||
// Solve the accuracy problem of JS decimal calculation by converting the value to integer.
|
// Solve the accuracy problem of JS decimal calculation by converting the value to integer.
|
||||||
return this.toPrecision((precisionFactor * val + precisionFactor * step) / precisionFactor);
|
return this.toPrecision((precisionFactor * val + precisionFactor * step) / precisionFactor);
|
||||||
},
|
},
|
||||||
_decrease(val, step) {
|
_decrease(val, step) {
|
||||||
if (typeof val !== 'number' && val !== undefined) return this.currentValue;
|
if (typeof val !== 'number' && val !== undefined) return this.currentValue;
|
||||||
|
|
||||||
const precisionFactor = Math.pow(10, this.precision);
|
const precisionFactor = Math.pow(10, this.numPrecision);
|
||||||
|
|
||||||
return this.toPrecision((precisionFactor * val - precisionFactor * step) / precisionFactor);
|
return this.toPrecision((precisionFactor * val - precisionFactor * step) / precisionFactor);
|
||||||
},
|
},
|
||||||
|
@ -183,17 +212,20 @@
|
||||||
},
|
},
|
||||||
handleBlur(event) {
|
handleBlur(event) {
|
||||||
this.$emit('blur', event);
|
this.$emit('blur', event);
|
||||||
this.$refs.input.setCurrentValue(this.currentValue);
|
this.$refs.input.setCurrentValue(this.currentInputValue);
|
||||||
},
|
},
|
||||||
handleFocus(event) {
|
handleFocus(event) {
|
||||||
this.$emit('focus', event);
|
this.$emit('focus', event);
|
||||||
},
|
},
|
||||||
setCurrentValue(newVal) {
|
setCurrentValue(newVal) {
|
||||||
const oldVal = this.currentValue;
|
const oldVal = this.currentValue;
|
||||||
|
if (typeof newVal === 'number' && this.precision !== undefined) {
|
||||||
|
newVal = this.toPrecision(newVal, this.precision);
|
||||||
|
}
|
||||||
if (newVal >= this.max) newVal = this.max;
|
if (newVal >= this.max) newVal = this.max;
|
||||||
if (newVal <= this.min) newVal = this.min;
|
if (newVal <= this.min) newVal = this.min;
|
||||||
if (oldVal === newVal) {
|
if (oldVal === newVal) {
|
||||||
this.$refs.input.setCurrentValue(this.currentValue);
|
this.$refs.input.setCurrentValue(this.currentInputValue);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.$emit('input', newVal);
|
this.$emit('input', newVal);
|
||||||
|
|
|
@ -220,6 +220,51 @@ describe('InputNumber', () => {
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
describe('precision', () => {
|
||||||
|
it('precision is 2', () => {
|
||||||
|
vm = createVue({
|
||||||
|
template: `
|
||||||
|
<el-input-number v-model="value" :max="8" :precision="2">
|
||||||
|
</el-input-number>
|
||||||
|
`,
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
value: 6.999
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
expect(vm.value === 7);
|
||||||
|
expect(vm.$el.querySelector('input').value).to.be.equal('7.00');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('precision greater than the precision of step', done => {
|
||||||
|
vm = createVue({
|
||||||
|
template: `
|
||||||
|
<el-input-number v-model="value" :max="8" :precision="0" :step="0.1">
|
||||||
|
</el-input-number>
|
||||||
|
`,
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
value: 6.999
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
const input = vm.$el.querySelector('input');
|
||||||
|
const btnIncrease = vm.$el.querySelector('.el-input-number__increase');
|
||||||
|
|
||||||
|
expect(vm.value === 7);
|
||||||
|
expect(input.value).to.be.equal('7');
|
||||||
|
|
||||||
|
triggerEvent(btnIncrease, 'mousedown');
|
||||||
|
triggerClick(document, 'mouseup');
|
||||||
|
|
||||||
|
vm.$nextTick(_ => {
|
||||||
|
expect(vm.value).to.be.equal(7);
|
||||||
|
expect(input.value).to.be.equal('7');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
it('controls', () => {
|
it('controls', () => {
|
||||||
vm = createVue({
|
vm = createVue({
|
||||||
template: `
|
template: `
|
||||||
|
|
|
@ -34,6 +34,9 @@ export declare class ElInputNumber extends ElementUIComponent {
|
||||||
/** Same as name in native input */
|
/** Same as name in native input */
|
||||||
name: string
|
name: string
|
||||||
|
|
||||||
|
/** Precision of input value */
|
||||||
|
precision: Number
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Focus the Input component
|
* Focus the Input component
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue