如何在 Element UI DatePicker 中接受较短的用户输入?
How to accept shorter user input into Element UI DatePicker?
在现有代码库中,更新了 ElementUI 和 Vue2 包。用户依赖于过时的 DatePicker UI 组件中看似意外的行为。
在 DatePicker 元素的输入字段中,日期的可视化格式为 30/01/2022
。
为了加快输入速度,用户改为在字段中输入 30012022
。此行为在更新后消失。只有输入带有 / 分隔符的日期才会被接受。
如何覆盖 ElementUI 日期时间组件的供应商方法以简化输入验证?
替换验证可以通过将 el-date-picker 包装到您自己的组件中来完成。诀窍是在 mounted()
中使用 $nextTick
,然后通过包装组件上的 reference 访问要替换的方法。
使用 TypeScript 的 .vue 文件的小代码示例:
<template>
<el-date-picker
ref="customDatePicker"
:type="type"
:size="size"
:value="value"
:clearable="clearable"
:format="displayFormat"
:value-format="valueFormat" />
</template>
<script lang="ts">
import moment from 'moment'
import { Component, Prop, Vue } from 'vue-property-decorator'
type PickerType = 'year' | 'month' | 'date' | 'dates' | 'datetime' | ' week' | 'datetimerange' | 'daterange' | 'monthrange'
type Size = 'large' | 'small' | 'mini'
@Component
export default class RexDatePicker extends Vue {
@Prop()
readonly value: any
@Prop({ type: String, default: 'small' })
readonly size!: Size
@Prop({ type: String, default: 'date' })
readonly type!: PickerType
@Prop({ type: String, default: 'yyyy-MM-dd' })
readonly valueFormat!: string
data() {
return {
clearable: this.$attrs.clearable !== 'false'
}
}
get displayFormat() : string {
if (this.type === 'year') {
return 'yyyy'
}
return 'dd/MM/yyyy'
}
mounted() {
this.$nextTick(() => {
var elPicker: any = this.$refs.customDatePicker
if (this.type === 'date' || this.type === 'daterange') {
// inject custom date input behavior
const originalParseFunction = elPicker.parseString
elPicker.parseString = function (value) {
value = expandNumbersToDate(value)
return originalParseFunction(value)
}
}
})
}
}
function expandNumbersToDate(value) {
// expects String, Date or an Array of those two
if (Object.prototype.toString.call(value) === '[object String]') {
var currentMonth = moment().format('MM')
var currentYear = moment().format('YYYY')
value = value.replace(/^[^\d]*(\d{2})[^\d]*$/, `/${currentMonth}/${currentYear}`)
value = value.replace(/^[^\d]*(\d{2})(\d{2})[^\d]*$/, `//${currentYear}`)
value = value.replace(/^[^\d]*(\d{2})\/?(\d{2})\/?(\d{4})[^\d]*$/, '//')
}
if (Array.isArray(value)) {
value = value.map(date => expandNumbersToDate(date))
}
return value
}
</script>
在现有代码库中,更新了 ElementUI 和 Vue2 包。用户依赖于过时的 DatePicker UI 组件中看似意外的行为。
在 DatePicker 元素的输入字段中,日期的可视化格式为 30/01/2022
。
为了加快输入速度,用户改为在字段中输入 30012022
。此行为在更新后消失。只有输入带有 / 分隔符的日期才会被接受。
如何覆盖 ElementUI 日期时间组件的供应商方法以简化输入验证?
替换验证可以通过将 el-date-picker 包装到您自己的组件中来完成。诀窍是在 mounted()
中使用 $nextTick
,然后通过包装组件上的 reference 访问要替换的方法。
使用 TypeScript 的 .vue 文件的小代码示例:
<template>
<el-date-picker
ref="customDatePicker"
:type="type"
:size="size"
:value="value"
:clearable="clearable"
:format="displayFormat"
:value-format="valueFormat" />
</template>
<script lang="ts">
import moment from 'moment'
import { Component, Prop, Vue } from 'vue-property-decorator'
type PickerType = 'year' | 'month' | 'date' | 'dates' | 'datetime' | ' week' | 'datetimerange' | 'daterange' | 'monthrange'
type Size = 'large' | 'small' | 'mini'
@Component
export default class RexDatePicker extends Vue {
@Prop()
readonly value: any
@Prop({ type: String, default: 'small' })
readonly size!: Size
@Prop({ type: String, default: 'date' })
readonly type!: PickerType
@Prop({ type: String, default: 'yyyy-MM-dd' })
readonly valueFormat!: string
data() {
return {
clearable: this.$attrs.clearable !== 'false'
}
}
get displayFormat() : string {
if (this.type === 'year') {
return 'yyyy'
}
return 'dd/MM/yyyy'
}
mounted() {
this.$nextTick(() => {
var elPicker: any = this.$refs.customDatePicker
if (this.type === 'date' || this.type === 'daterange') {
// inject custom date input behavior
const originalParseFunction = elPicker.parseString
elPicker.parseString = function (value) {
value = expandNumbersToDate(value)
return originalParseFunction(value)
}
}
})
}
}
function expandNumbersToDate(value) {
// expects String, Date or an Array of those two
if (Object.prototype.toString.call(value) === '[object String]') {
var currentMonth = moment().format('MM')
var currentYear = moment().format('YYYY')
value = value.replace(/^[^\d]*(\d{2})[^\d]*$/, `/${currentMonth}/${currentYear}`)
value = value.replace(/^[^\d]*(\d{2})(\d{2})[^\d]*$/, `//${currentYear}`)
value = value.replace(/^[^\d]*(\d{2})\/?(\d{2})\/?(\d{4})[^\d]*$/, '//')
}
if (Array.isArray(value)) {
value = value.map(date => expandNumbersToDate(date))
}
return value
}
</script>