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