element/packages/input-number/src/input-number.vue

247 lines
6.7 KiB
Vue
Raw Normal View History

2016-07-27 06:15:02 +00:00
<template>
<div class="el-input-number"
:class="[
2017-10-12 09:50:06 +00:00
inputNumberSize ? 'el-input-number--' + inputNumberSize : '',
{ 'is-disabled': disabled },
{ 'is-without-controls': !controls },
{ 'is-controls-right': controlsAtRight }
2016-07-27 06:15:02 +00:00
]"
>
<span
v-if="controls"
2017-02-22 02:28:03 +00:00
class="el-input-number__decrease"
2016-07-27 06:15:02 +00:00
:class="{'is-disabled': minDisabled}"
2016-08-11 07:51:13 +00:00
v-repeat-click="decrease"
@keydown.enter="decrease"
role="button"
2016-07-27 06:15:02 +00:00
>
<i :class="`el-icon-${controlsAtRight ? 'arrow-down' : 'minus'}`"></i>
2016-07-27 06:15:02 +00:00
</span>
<span
v-if="controls"
2017-02-22 02:28:03 +00:00
class="el-input-number__increase"
2016-07-27 06:15:02 +00:00
:class="{'is-disabled': maxDisabled}"
2016-08-11 07:51:13 +00:00
v-repeat-click="increase"
@keydown.enter="increase"
role="button"
2016-07-27 06:15:02 +00:00
>
<i :class="`el-icon-${controlsAtRight ? 'arrow-up' : 'plus'}`"></i>
2016-07-27 06:15:02 +00:00
</span>
<el-input
2017-01-10 16:39:35 +00:00
:value="currentValue"
@keydown.up.native.prevent="increase"
@keydown.down.native.prevent="decrease"
@blur="handleBlur"
@focus="handleFocus"
@input="debounceHandleInput"
:disabled="disabled"
2017-10-12 09:50:06 +00:00
:size="inputNumberSize"
:max="max"
:min="min"
:name="name"
2016-12-27 11:14:22 +00:00
ref="input"
:label="label"
>
<template slot="prepend" v-if="$slots.prepend">
<slot name="prepend"></slot>
</template>
<template slot="append" v-if="$slots.append">
<slot name="append"></slot>
</template>
</el-input>
2016-07-27 06:15:02 +00:00
</div>
</template>
<script>
2016-10-25 13:35:41 +00:00
import ElInput from 'element-ui/packages/input';
import debounce from 'throttle-debounce/debounce';
import Focus from 'element-ui/src/mixins/focus';
2017-10-11 10:00:58 +00:00
import RepeatClick from 'element-ui/src/directives/repeat-click';
2016-07-27 06:15:02 +00:00
export default {
name: 'ElInputNumber',
mixins: [Focus('input')],
inject: {
elFormItem: {
default: ''
}
},
2016-07-27 06:15:02 +00:00
directives: {
2017-10-11 10:00:58 +00:00
repeatClick: RepeatClick
2016-07-27 06:15:02 +00:00
},
components: {
ElInput
},
props: {
step: {
type: Number,
default: 1
},
max: {
type: Number,
default: Infinity
},
min: {
type: Number,
default: -Infinity
},
value: {
default: 0
},
disabled: Boolean,
size: String,
controls: {
type: Boolean,
default: true
},
controlsPosition: {
type: String,
default: ''
},
debounce: {
type: Number,
default: 300
},
name: String,
label: String
},
2016-07-27 06:15:02 +00:00
data() {
return {
2017-01-11 17:52:57 +00:00
currentValue: 0
2016-07-27 06:15:02 +00:00
};
},
2016-08-11 07:51:13 +00:00
watch: {
2017-01-11 17:52:57 +00:00
value: {
immediate: true,
handler(value) {
let newVal = Number(value);
if (isNaN(newVal)) return;
if (newVal >= this.max) newVal = this.max;
if (newVal <= this.min) newVal = this.min;
2017-01-10 16:39:35 +00:00
this.currentValue = newVal;
2017-01-11 17:52:57 +00:00
this.$emit('input', newVal);
2016-08-11 07:51:13 +00:00
}
}
},
2016-07-27 06:15:02 +00:00
computed: {
minDisabled() {
return this._decrease(this.value, this.step) < this.min;
2016-07-27 06:15:02 +00:00
},
maxDisabled() {
return this._increase(this.value, this.step) > this.max;
},
precision() {
const { value, step, getPrecision } = this;
return Math.max(getPrecision(value), getPrecision(step));
},
controlsAtRight() {
return this.controlsPosition === 'right';
2017-10-12 09:50:06 +00:00
},
_elFormItemSize() {
return (this.elFormItem || {}).elFormItemSize;
},
inputNumberSize() {
return this.size || this._elFormItemSize || (this.$ELEMENT || {}).size;
2016-07-27 06:15:02 +00:00
}
},
methods: {
toPrecision(num, precision) {
if (precision === undefined) precision = this.precision;
return parseFloat(parseFloat(Number(num).toFixed(precision)));
2016-09-01 07:56:04 +00:00
},
getPrecision(value) {
const valueString = value.toString();
const dotPosition = valueString.indexOf('.');
let precision = 0;
if (dotPosition !== -1) {
precision = valueString.length - dotPosition - 1;
2016-09-01 07:56:04 +00:00
}
return precision;
},
_increase(val, step) {
if (typeof val !== 'number') return this.currentValue;
const precisionFactor = Math.pow(10, this.precision);
return this.toPrecision((precisionFactor * val + precisionFactor * step) / precisionFactor);
},
_decrease(val, step) {
if (typeof val !== 'number') return this.currentValue;
const precisionFactor = Math.pow(10, this.precision);
return this.toPrecision((precisionFactor * val - precisionFactor * step) / precisionFactor);
2016-09-01 07:56:04 +00:00
},
2016-07-27 06:15:02 +00:00
increase() {
if (this.disabled || this.maxDisabled) return;
2016-11-24 06:48:56 +00:00
const value = this.value || 0;
const newVal = this._increase(value, this.step);
if (newVal > this.max) return;
2017-01-10 16:39:35 +00:00
this.setCurrentValue(newVal);
2016-07-27 06:15:02 +00:00
},
decrease() {
if (this.disabled || this.minDisabled) return;
2016-11-24 06:48:56 +00:00
const value = this.value || 0;
const newVal = this._decrease(value, this.step);
if (newVal < this.min) return;
2017-01-10 16:39:35 +00:00
this.setCurrentValue(newVal);
},
handleBlur(event) {
this.$emit('blur', event);
2016-12-27 11:14:22 +00:00
this.$refs.input.setCurrentValue(this.currentValue);
2017-01-10 16:39:35 +00:00
},
handleFocus(event) {
this.$emit('focus', event);
},
2017-01-10 16:39:35 +00:00
setCurrentValue(newVal) {
const oldVal = this.currentValue;
2017-01-11 17:52:57 +00:00
if (newVal >= this.max) newVal = this.max;
if (newVal <= this.min) newVal = this.min;
if (oldVal === newVal) {
this.$refs.input.setCurrentValue(this.currentValue);
return;
}
2017-01-11 17:52:57 +00:00
this.$emit('change', newVal, oldVal);
this.$emit('input', newVal);
this.currentValue = newVal;
2017-01-10 16:39:35 +00:00
},
handleInput(value) {
if (value === '') {
return;
}
2017-10-30 07:28:45 +00:00
if (value.indexOf('.') === (value.length - 1)) {
return;
}
if (value.indexOf('-') === (value.length - 1)) {
return;
}
2017-01-10 16:39:35 +00:00
const newVal = Number(value);
if (!isNaN(newVal)) {
this.setCurrentValue(newVal);
} else {
this.$refs.input.setCurrentValue(this.currentValue);
2017-01-10 16:39:35 +00:00
}
2016-07-27 06:15:02 +00:00
}
},
created() {
this.debounceHandleInput = debounce(this.debounce, value => {
this.handleInput(value);
});
},
mounted() {
let innerInput = this.$refs.input.$refs.input;
innerInput.setAttribute('role', 'spinbutton');
innerInput.setAttribute('aria-valuemax', this.max);
innerInput.setAttribute('aria-valuemin', this.min);
innerInput.setAttribute('aria-valuenow', this.currentValue);
innerInput.setAttribute('aria-disabled', this.disabled);
},
updated() {
let innerInput = this.$refs.input.$refs.input;
innerInput.setAttribute('aria-valuenow', this.currentValue);
2016-07-27 06:15:02 +00:00
}
};
</script>