In an existing code base the ElementUI and Vue2 packages got updated. The users are relying on what looks to be unintended behavior from the outdated DatePicker UI component.
The date is visually formatted as 30/01/2022
in the input field of the DatePicker elements.
To speed up typing users were entering 30012022
into the field instead. This behavior disappeared after the updates. Only entering the date with the / separator gets accepted.
How do I overwrite the vendor methods of the ElementUI Date Time component to ease the input validation?
Replacing validation can be done by wrapping the el-date-picker into your own component. The trick is to use $nextTick
inside mounted()
and then access the method you want to replace through a reference on the wrapped component.
A small code example of the .vue file using TypeScript:
<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]*$/, `$1/${currentMonth}/${currentYear}`)
value = value.replace(/^[^\d]*(\d{2})(\d{2})[^\d]*$/, `$1/$2/${currentYear}`)
value = value.replace(/^[^\d]*(\d{2})\/?(\d{2})\/?(\d{4})[^\d]*$/, '$1/$2/$3')
}
if (Array.isArray(value)) {
value = value.map(date => expandNumbersToDate(date))
}
return value
}
</script>