feat(input-number): validator

This commit is contained in:
07akioni 2019-10-30 18:10:11 +08:00
parent 95b6ce1c52
commit 26bc4952c3
6 changed files with 98 additions and 55 deletions

View File

@ -3,6 +3,7 @@
<n-input-number <n-input-number
v-model="value" v-model="value"
@change="handleChange" @change="handleChange"
@blur="handleBlur"
/> />
``` ```
```js ```js
@ -15,7 +16,10 @@ export default {
methods: { methods: {
handleChange (newValue) { handleChange (newValue) {
this.$NMessage.info(`value: ${newValue}`) this.$NMessage.info(`value: ${newValue}`)
} },
handleBlur (e, v) {
this.$NMessage.info(`blur: ` + v)
},
} }
} }
``` ```

View File

@ -6,4 +6,5 @@ event
min-max min-max
size size
step step
validator
``` ```

View File

@ -15,7 +15,7 @@
export default { export default {
data () { data () {
return { return {
value: 0 value: null
} }
} }
} }

View File

@ -0,0 +1,17 @@
# Validator
```html
<n-input-number
v-model="value"
:validator="validator"
/>
```
```js
export default {
data () {
return {
value: null,
validator: x => x > 0
}
}
}
```

View File

@ -12,7 +12,7 @@
type="button" type="button"
class="n-input-number__minus-button" class="n-input-number__minus-button"
:class="{ :class="{
[`n-input-number__minus-button--disabled`]: value !== null && safeMin !== null && value <= safeMin [`n-input-number__minus-button--disabled`]: !minusable
}" }"
@mousedown="handleMouseDown" @mousedown="handleMouseDown"
@click="minus" @click="minus"
@ -25,8 +25,8 @@
type="text" type="text"
:value="value" :value="value"
:disabled="disabled ? 'disabled' : false" :disabled="disabled ? 'disabled' : false"
@focus="handleFocus"
@blur="handleBlur" @blur="handleBlur"
@input="handleInput"
@keyup.enter="handleEnter" @keyup.enter="handleEnter"
> >
<button <button
@ -34,7 +34,7 @@
type="button" type="button"
class="n-input-number__add-button" class="n-input-number__add-button"
:class="{ :class="{
[`n-input-number__add-button--disabled`]: value !== null && safeMax !== null && value >= safeMax [`n-input-number__add-button--disabled`]: !addable
}" }"
@mousedown="handleMouseDown" @mousedown="handleMouseDown"
@click="add" @click="add"
@ -107,6 +107,10 @@ export default {
disabled: { disabled: {
type: Boolean, type: Boolean,
default: false default: false
},
validator: {
type: Function,
default: null
} }
}, },
computed: { computed: {
@ -120,12 +124,29 @@ export default {
if (parsedNumber !== null) return parsedNumber if (parsedNumber !== null) return parsedNumber
else return null else return null
}, },
minusable () {
if (this.validator) {
if (this.value !== null) return this.validator(this.value - this.step)
else return false
} else {
return !(this.value !== null && this.safeMin !== null && this.value <= this.safeMin)
}
},
addable () {
if (this.validator) {
if (this.value !== null) return this.validator(this.value + this.step)
else return false
} else {
return !(this.value !== null && this.safeMax !== null && this.value >= this.safeMax)
}
},
safeMax () { safeMax () {
const parsedNumber = parseNumber(this.max) const parsedNumber = parseNumber(this.max)
if (parsedNumber !== null) return parsedNumber if (parsedNumber !== null) return parsedNumber
else return null else return null
}, },
aValidValue () { aValidValue () {
if (this.validator) return null
if (this.safeMin !== null) { if (this.safeMin !== null) {
return Math.max(0, this.safeMin) return Math.max(0, this.safeMin)
} else if (this.safeMax !== null) { } else if (this.safeMax !== null) {
@ -137,29 +158,12 @@ export default {
}, },
watch: { watch: {
value (newValue, oldValue) { value (newValue, oldValue) {
if (newValue !== null) { const adjustedValue = this.adjustValue(newValue)
if (this.safeMax !== null && newValue > this.safeMax) { if (adjustedValue === newValue) {
newValue = this.safeMax
}
if (this.safeMin !== null && newValue < this.safeMin) {
newValue = this.safeMin
}
}
this.$emit('change', newValue, oldValue) this.$emit('change', newValue, oldValue)
this.formBlur('change', newValue) this.formBlur('change', newValue)
/** } else {
* newValue === oldValue won't trigger watcher! this.$emit('input', adjustedValue)
* so the call stack won't fall in loop
*/
this.$emit('input', newValue)
}
},
created () {
if (this.value !== null) {
if (this.safeMax !== null && this.value > this.safeMax) {
this.$emit('input', this.safeMax)
} else if (this.safeMin !== null && this.value < this.safeMin) {
this.$emit('input', this.safeMin)
} }
} }
}, },
@ -175,44 +179,62 @@ export default {
this.dispatch('NFormItem', 'on-form-' + type, val) this.dispatch('NFormItem', 'on-form-' + type, val)
} }
}, },
handleFocus (e) {
this.$emit('focus', e, this.value)
},
add () { add () {
if (!this.addable) return
if (this.value === null) { if (this.value === null) {
this.$emit('input', this.aValidValue) this.$emit('input', this.aValidValue)
} else { } else {
const valueAfterChange = this.value + this.safeStep const valueAfterChange = this.adjustValue(this.value + this.safeStep)
this.$emit('input', valueAfterChange) this.$emit('input', valueAfterChange)
} }
}, },
minus () { minus () {
console.log('minus', this.minusable)
if (!this.minusable) return
if (this.value === null) { if (this.value === null) {
this.$emit('input', this.aValidValue) this.$emit('input', this.aValidValue)
} else { } else {
const valueAfterChange = this.value - this.safeStep const valueAfterChange = this.adjustValue(this.value - this.safeStep)
this.$emit('input', valueAfterChange) this.$emit('input', valueAfterChange)
} }
},
handleInput (e) {
}, },
handleEnter (e) { handleEnter (e) {
this.$refs.input.blur() const value = this.adjustValue(this.$refs.input.value)
this.$refs.input.value = value
this.$emit('input', value)
},
adjustValue (value) {
value = String(value).trim() || ''
if (value.trim() === '') {
value = null
} else if (Number.isNaN(Number(value))) {
value = this.value
} else {
value = Number(value)
}
if (value === null) {
return null
} if (this.validator) {
if (this.validator(value)) {
return value
} else {
return null
}
} else {
if (this.safeMin !== null && value < this.safeMin) value = this.safeMin
else if (this.safeMax !== null && value > this.safeMax) value = this.safeMax
}
return value
}, },
handleBlur (e) { handleBlur (e) {
const value = e.target.value const value = this.adjustValue(e.target.value)
if (value === '') { e.target.value = value
this.$emit('input', null) this.$emit('input', value)
this.$emit('blur', e, value)
this.formBlur('blur', value) this.formBlur('blur', value)
return
}
const parsedNumber = Number(value)
if (Number.isNaN(parsedNumber)) {
e.target.value = String(this.value)
} else {
const valueAfterChange = parsedNumber
e.target.value = String(parsedNumber)
this.$emit('input', valueAfterChange)
}
this.formBlur('blur', parsedNumber)
} }
} }
} }

View File

@ -25,7 +25,7 @@
// background: map-get($--input-number-background-color, 'disabled'); // background: map-get($--input-number-background-color, 'disabled');
@include e(minus-button, add-button) { @include e(minus-button, add-button) {
background: map-get($--input-number-button-background-color, 'disabled'); background: map-get($--input-number-button-background-color, 'disabled');
color: map-get($--input-number-button-text-color, 'disabled'); fill: map-get($--input-number-button-text-color, 'disabled');
pointer-events: none; pointer-events: none;
} }
@include e(input) { @include e(input) {
@ -61,11 +61,9 @@
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
path {
fill: map-get($--input-number-button-text-color, 'default'); fill: map-get($--input-number-button-text-color, 'default');
}
font-size: 14px; font-size: 14px;
transition: color .3s $default-cubic-bezier, background-color .3s $default-cubic-bezier, box-shadow .3s $default-cubic-bezier; transition: fill .3s $default-cubic-bezier, background-color .3s $default-cubic-bezier, box-shadow .3s $default-cubic-bezier;
box-shadow: inset 0 0 0px 1px map-get($--input-number-border-color, 'default'); box-shadow: inset 0 0 0px 1px map-get($--input-number-border-color, 'default');
&:hover ~ { &:hover ~ {
@include e(border-layer) { @include e(border-layer) {
@ -81,8 +79,9 @@
background-color: map-get($--input-number-button-background-color, 'active') background-color: map-get($--input-number-button-background-color, 'active')
} }
@include m(disabled) { @include m(disabled) {
cursor: not-allowed;
background-color: map-get($--input-number-button-background-color, 'disabled'); background-color: map-get($--input-number-button-background-color, 'disabled');
color: map-get($--input-number-button-text-color, 'disabled'); fill: map-get($--input-number-button-text-color, 'disabled');
} }
} }
@include e(minus-button) { @include e(minus-button) {