From 2e58b8259dc5ff93196e9f2180427f4fa08310de Mon Sep 17 00:00:00 2001 From: btea <2356281422@qq.com> Date: Tue, 25 Mar 2025 10:09:47 +0800 Subject: [PATCH] fix(components): [date-picker] config format manual change value invalid (#20223) * fix(components): [date-picker] config format manual change value invalid * fix: update --- .../date-picker/__tests__/date-picker.test.ts | 23 +++++++++++++++++++ .../src/date-picker-com/panel-date-pick.vue | 11 +++++++-- .../src/date-picker-com/panel-date-range.vue | 8 ++++++- .../src/date-picker-com/panel-month-range.vue | 8 ++++++- .../src/date-picker-com/panel-year-range.vue | 8 ++++++- .../date-picker/src/date-picker.tsx | 7 ++++-- packages/components/date-picker/src/utils.ts | 14 +++++++---- 7 files changed, 67 insertions(+), 12 deletions(-) diff --git a/packages/components/date-picker/__tests__/date-picker.test.ts b/packages/components/date-picker/__tests__/date-picker.test.ts index cec56033ab..bdb229ea7f 100644 --- a/packages/components/date-picker/__tests__/date-picker.test.ts +++ b/packages/components/date-picker/__tests__/date-picker.test.ts @@ -478,6 +478,29 @@ describe('DatePicker', () => { expect(dayjs(wrapper.vm.value).format('YYYY-MM-DD')).toBe('2023-10-01') }) + it('validate manual change value with format', async () => { + const wrapper = _mount( + ``, + () => ({ + value: '', + }) + ) + const input = wrapper.find('input') + input.element.value = '01.10.2023' + await input.trigger('input') + await input.trigger('blur') + expect(dayjs(wrapper.vm.value).format('YYYY-MM-DD')).toBe('2023-10-01') + + input.element.value = '02.10.2023' + await input.trigger('input') + await input.trigger('blur') + + expect(dayjs(wrapper.vm.value).format('YYYY-MM-DD')).toBe('2023-10-02') + }) + it('ref focus', async () => { _mount( ` { const newDate = correctlyParseUserInput( value, dateFormat.value, - lang.value + lang.value, + isDefaultFormat ) as Dayjs if (newDate.isValid()) { if (disabledDate && disabledDate(newDate.toDate())) { @@ -651,7 +653,12 @@ const formatToString = (value: Dayjs | Dayjs[]) => { } const parseUserInput = (value: Dayjs) => { - return correctlyParseUserInput(value, props.format, lang.value) + return correctlyParseUserInput( + value, + props.format, + lang.value, + isDefaultFormat + ) } const getDefaultValue = () => { diff --git a/packages/components/date-picker/src/date-picker-com/panel-date-range.vue b/packages/components/date-picker/src/date-picker-com/panel-date-range.vue index e7b8c1647c..9cd7fb1832 100644 --- a/packages/components/date-picker/src/date-picker-com/panel-date-range.vue +++ b/packages/components/date-picker/src/date-picker-com/panel-date-range.vue @@ -313,6 +313,7 @@ const emit = defineEmits([ const unit = 'month' // FIXME: fix the type for ep picker const pickerBase = inject('EP_PICKER_BASE') as any +const isDefaultFormat = inject('ElIsDefaultFormat') as any const { disabledDate, cellClassName, defaultTime, clearable } = pickerBase.props const format = toRef(pickerBase.props, 'format') const shortcuts = toRef(pickerBase.props, 'shortcuts') @@ -722,7 +723,12 @@ const formatToString = (value: Dayjs | Dayjs[]) => { } const parseUserInput = (value: Dayjs | Dayjs[]) => { - return correctlyParseUserInput(value, format.value, lang.value) + return correctlyParseUserInput( + value, + format.value, + lang.value, + isDefaultFormat + ) } function onParsedValueChanged( diff --git a/packages/components/date-picker/src/date-picker-com/panel-month-range.vue b/packages/components/date-picker/src/date-picker-com/panel-month-range.vue index 44a343f74d..4fc56dab59 100644 --- a/packages/components/date-picker/src/date-picker-com/panel-month-range.vue +++ b/packages/components/date-picker/src/date-picker-com/panel-month-range.vue @@ -138,6 +138,7 @@ const unit = 'year' const { lang } = useLocale() const pickerBase = inject('EP_PICKER_BASE') as any +const isDefaultFormat = inject('ElIsDefaultFormat') as any const { shortcuts, disabledDate } = pickerBase.props const format = toRef(pickerBase.props, 'format') const defaultValue = toRef(pickerBase.props, 'defaultValue') @@ -224,7 +225,12 @@ const formatToString = (value: Dayjs | Dayjs[]) => { } const parseUserInput = (value: Dayjs | Dayjs[]) => { - return correctlyParseUserInput(value, format.value, lang.value) + return correctlyParseUserInput( + value, + format.value, + lang.value, + isDefaultFormat + ) } function onParsedValueChanged( diff --git a/packages/components/date-picker/src/date-picker-com/panel-year-range.vue b/packages/components/date-picker/src/date-picker-com/panel-year-range.vue index ad073d1748..40762b67a9 100644 --- a/packages/components/date-picker/src/date-picker-com/panel-year-range.vue +++ b/packages/components/date-picker/src/date-picker-com/panel-year-range.vue @@ -123,6 +123,7 @@ const leftDate = ref(dayjs().locale(lang.value)) const rightDate = ref(leftDate.value.add(10, 'year')) const { pickerNs: ppNs } = inject(ROOT_PICKER_INJECTION_KEY)! const drpNs = useNamespace('date-range-picker') +const isDefaultFormat = inject('isDefaultFormat') as any const hasShortcuts = computed(() => !!shortcuts.length) @@ -287,7 +288,12 @@ watch( ) const parseUserInput = (value: Dayjs | Dayjs[]) => { - return correctlyParseUserInput(value, format.value, lang.value) + return correctlyParseUserInput( + value, + format.value, + lang.value, + isDefaultFormat + ) } const formatToString = (value: Dayjs[] | Dayjs) => { diff --git a/packages/components/date-picker/src/date-picker.tsx b/packages/components/date-picker/src/date-picker.tsx index 9c1e02973c..eb267b5404 100644 --- a/packages/components/date-picker/src/date-picker.tsx +++ b/packages/components/date-picker/src/date-picker.tsx @@ -1,4 +1,4 @@ -import { defineComponent, provide, reactive, ref, toRef } from 'vue' +import { computed, defineComponent, provide, reactive, ref, toRef } from 'vue' import dayjs from 'dayjs' import customParseFormat from 'dayjs/plugin/customParseFormat.js' import advancedFormat from 'dayjs/plugin/advancedFormat.js' @@ -39,7 +39,10 @@ export default defineComponent({ emits: [UPDATE_MODEL_EVENT], setup(props, { expose, emit, slots }) { const ns = useNamespace('picker-panel') - + const isDefaultFormat = computed(() => { + return !props.format + }) + provide('ElIsDefaultFormat', isDefaultFormat) provide('ElPopperOptions', reactive(toRef(props, 'popperOptions'))) provide(ROOT_PICKER_INJECTION_KEY, { slots, diff --git a/packages/components/date-picker/src/utils.ts b/packages/components/date-picker/src/utils.ts index 50beadbe2d..2249e6fd2b 100644 --- a/packages/components/date-picker/src/utils.ts +++ b/packages/components/date-picker/src/utils.ts @@ -1,7 +1,8 @@ import dayjs from 'dayjs' -import { isArray } from '@element-plus/utils' +import { isArray, isString } from '@element-plus/utils' import { rangeArr } from '@element-plus/components/time-picker' +import type { ComputedRef } from 'vue' import type { Dayjs } from 'dayjs' import type { DateCell } from './date-picker.type' import type { DisabledDateType } from './props/shared' @@ -185,13 +186,16 @@ export const getValidDateOfYear = ( export const correctlyParseUserInput = ( value: string | Dayjs | Dayjs[], format: string, - lang: string + lang: string, + defaultFormat: ComputedRef ): Dayjs | Dayjs[] => { if (isArray(value)) { - return value.map((v) => correctlyParseUserInput(v, format, lang) as Dayjs) + return value.map( + (v) => correctlyParseUserInput(v, format, lang, defaultFormat) as Dayjs + ) } - if (typeof value === 'string') { - const dayjsValue = dayjs(value) + if (isString(value)) { + const dayjsValue = defaultFormat.value ? dayjs(value) : dayjs(value, format) if (!dayjsValue.isValid()) { // return directly if not valid return dayjsValue