From a985f511a0ca43d2e8972c4efa9ba69022491031 Mon Sep 17 00:00:00 2001 From: Noblet Ouways <91417411+Dsaquel@users.noreply.github.com> Date: Thu, 21 Aug 2025 14:01:27 +0200 Subject: [PATCH] chore: date-picker-panel tweaks (#21827) * docs(components): [date-picker-panel] add missing props & make the doc clearer * fix(components): [date-picker-panel] set default time-format & date-format * refactor(components): [date-picker-panel] remove `format` property --- docs/en-US/component/date-picker-panel.md | 3 +- docs/en-US/component/datetime-picker.md | 4 +- .../__tests__/date-picker-panel.test.tsx | 16 +++-- .../src/date-picker-com/panel-date-pick.vue | 13 +++- .../src/date-picker-com/panel-date-range.vue | 22 +++++-- .../src/date-picker-com/panel-month-range.vue | 3 +- .../src/date-picker-com/panel-year-range.vue | 3 +- .../src/date-picker-panel.tsx | 34 +--------- .../src/props/date-picker-panel.ts | 8 +-- .../components/date-picker-panel/src/utils.ts | 6 +- .../__tests__/date-time-picker.test.tsx | 62 +++++++++++++++++++ .../time-picker/src/common/props.ts | 4 +- 12 files changed, 114 insertions(+), 64 deletions(-) diff --git a/docs/en-US/component/date-picker-panel.md b/docs/en-US/component/date-picker-panel.md index f8230b9cbd..e1512fefd1 100644 --- a/docs/en-US/component/date-picker-panel.md +++ b/docs/en-US/component/date-picker-panel.md @@ -65,10 +65,11 @@ Note, date time locale (month name, first day of the week ...) are also configur | disabled | whether DatePicker is disabled | ^[boolean] | false | | clearable | whether to show clear button | ^[boolean] | true | | type | type of the picker | ^[enum]`'year' \| 'years' \|'month' \| 'months' \| 'date' \| 'dates' \| 'datetime' \| 'week' \| 'datetimerange' \| 'daterange' \| 'monthrange' \| 'yearrange'` | date | -| format | format of the displayed value in the input box (in datetime/datetimerange mode) | ^[string] | YYYY-MM-DD | | default-value | optional, default date of the calendar | ^[object]`Date \| [Date, Date]` | — | | default-time | optional, the time value to use when selecting date range | ^[object]`Date \| [Date, Date]` | — | | value-format | optional, format of binding value. If not specified, the binding value will be a Date object | ^[string] | — | +| date-format | optional, format of the date displayed in input's inner panel | ^[string] see [date formats](https://day.js.org/docs/en/display/format) | YYYY-MM-DD | +| time-format | optional, format of the time displayed in input's inner panel | ^[string] see [date formats](https://day.js.org/docs/en/display/format) | HH:mm:ss | | unlink-panels | unlink two date-panels in range-picker | ^[boolean] | false | | disabled-date | a function determining if a date is disabled with that date as its parameter. Should return a Boolean | ^[Function]`(data: Date) => boolean` | — | | shortcuts | an object array to set shortcut options | ^[object]`Array<{ text: string, value: Date \| Function }>` | [] | diff --git a/docs/en-US/component/datetime-picker.md b/docs/en-US/component/datetime-picker.md index c3960bff37..17f77f4d70 100644 --- a/docs/en-US/component/datetime-picker.md +++ b/docs/en-US/component/datetime-picker.md @@ -99,8 +99,8 @@ datetime-picker/custom-icon | default-value | optional, default date of the calendar | ^[object]`Date \| [Date, Date]` | — | | default-time | the default time value after picking a date. Time `00:00:00` will be used if not specified | ^[object]`Date \| [Date, Date]` | — | | value-format | optional, format of binding value. If not specified, the binding value will be a Date object | ^[string] see [date formats](https://day.js.org/docs/en/display/format) | — | -| date-format ^(2.4.0) | optional, format of the date displayed value in TimePicker's dropdown | ^[string] see [date formats](https://day.js.org/docs/en/display/format) | — | -| time-format ^(2.4.0) | optional, format of the time displayed value in TimePicker's dropdown | ^[string] see [date formats](https://day.js.org/docs/en/display/format) | — | +| date-format ^(2.4.0) | optional, format of the date displayed in input's inner panel | ^[string] see [date formats](https://day.js.org/docs/en/display/format) | YYYY-MM-DD | +| time-format ^(2.4.0) | optional, format of the time displayed in input's inner panel | ^[string] see [date formats](https://day.js.org/docs/en/display/format) | HH:mm:ss | | id | same as `id` in native input | ^[string] / ^[object]`[string, string]` | — | | name | same as `name` in native input | ^[string] | — | | unlink-panels | unlink two date-panels in range-picker | ^[boolean] | false | diff --git a/packages/components/date-picker-panel/__tests__/date-picker-panel.test.tsx b/packages/components/date-picker-panel/__tests__/date-picker-panel.test.tsx index fa6263e45e..0b6af3ef24 100644 --- a/packages/components/date-picker-panel/__tests__/date-picker-panel.test.tsx +++ b/packages/components/date-picker-panel/__tests__/date-picker-panel.test.tsx @@ -105,16 +105,14 @@ describe('DatePickerPanel', () => { describe(':type="datetime" & :type="datetimerange"', () => { describe(':type="datetime"', () => { - it('both picker show correct formated value (extract date-format and time-format from format property', async () => { + it('dateFormat & timeFormat', async () => { const value = ref(new Date(2018, 2, 5, 10, 15, 24)) - const format = ref('YYYY/MM/DD HH:mm A') - const dateFormat = ref('') - const timeFormat = ref('') + const dateFormat = ref('YYYY/MM/DD') + const timeFormat = ref('HH:mm A') const wrapper = mount(() => ( @@ -132,7 +130,8 @@ describe('DatePickerPanel', () => { expect(dateInput.value).toBe('2018/03/05') expect(timeInput.value).toBe('10:15 AM') - format.value = 'MM-DD-YYYY HH a' + dateFormat.value = 'MM-DD-YYYY' + timeFormat.value = 'HH a' await nextTick() expect(dateInput.value).toBe('03-05-2018') expect(timeInput.value).toBe('10 am') @@ -470,14 +469,13 @@ describe('DatePickerPanel', () => { new Date(2000, 10, 8, 10, 10), new Date(2000, 10, 11, 10, 10), ]) - const dateFormat = ref('') - const timeFormat = ref('') + const dateFormat = ref('YYYY/MM/DD') + const timeFormat = ref('HH:mm A') const wrapper = mount(() => ( { } const timeFormat = computed(() => { - return props.timeFormat || extractTimeFormat(props.format) + return ( + props.timeFormat || extractTimeFormat(props.format) || DEFAULT_FORMATS_TIME + ) }) const dateFormat = computed(() => { - return props.dateFormat || extractDateFormat(props.format) + return ( + props.dateFormat || extractDateFormat(props.format) || DEFAULT_FORMATS_DATE + ) }) const visibleTime = computed(() => { diff --git a/packages/components/date-picker-panel/src/date-picker-com/panel-date-range.vue b/packages/components/date-picker-panel/src/date-picker-com/panel-date-range.vue index 3f604b0eb2..f5b8f0b9c4 100644 --- a/packages/components/date-picker-panel/src/date-picker-com/panel-date-range.vue +++ b/packages/components/date-picker-panel/src/date-picker-com/panel-date-range.vue @@ -406,6 +406,8 @@ import { useLocale } from '@element-plus/hooks' import ElButton from '@element-plus/components/button' import ElInput from '@element-plus/components/input' import { + DEFAULT_FORMATS_DATE, + DEFAULT_FORMATS_TIME, PICKER_BASE_INJECTION_KEY, TimePickPanel, extractDateFormat, @@ -431,6 +433,7 @@ import YearTable from './basic-year-table.vue' import MonthTable from './basic-month-table.vue' import DateTable from './basic-date-table.vue' +import type { Ref } from 'vue' import type { Dayjs } from 'dayjs' type ChangeType = 'min' | 'max' @@ -451,10 +454,11 @@ const unit = 'month' // FIXME: fix the type for ep picker const pickerBase = inject(PICKER_BASE_INJECTION_KEY) as any const isDefaultFormat = inject( - ROOT_PICKER_IS_DEFAULT_FORMAT_INJECTION_KEY + ROOT_PICKER_IS_DEFAULT_FORMAT_INJECTION_KEY, + undefined ) as any const { disabledDate, cellClassName, defaultTime, clearable } = pickerBase.props -const format = toRef(pickerBase.props, 'format') +const format: Ref = toRef(pickerBase.props, 'format') const shortcuts = toRef(pickerBase.props, 'shortcuts') const defaultValue = toRef(pickerBase.props, 'defaultValue') const { lang } = useLocale() @@ -553,11 +557,19 @@ const maxVisibleTime = computed(() => { }) const timeFormat = computed(() => { - return props.timeFormat || extractTimeFormat(format.value) + return ( + props.timeFormat || + extractTimeFormat(format.value || '') || + DEFAULT_FORMATS_TIME + ) }) const dateFormat = computed(() => { - return props.dateFormat || extractDateFormat(format.value) + return ( + props.dateFormat || + extractDateFormat(format.value || '') || + DEFAULT_FORMATS_DATE + ) }) const isValidValue = (date: [Dayjs, Dayjs]) => { @@ -882,7 +894,7 @@ const formatToString = (value: Dayjs | Dayjs[]) => { const parseUserInput = (value: Dayjs | Dayjs[]) => { return correctlyParseUserInput( value, - format.value, + format.value || '', lang.value, isDefaultFormat ) diff --git a/packages/components/date-picker-panel/src/date-picker-com/panel-month-range.vue b/packages/components/date-picker-panel/src/date-picker-com/panel-month-range.vue index 1c3bc59e26..ded0b6fd35 100644 --- a/packages/components/date-picker-panel/src/date-picker-com/panel-month-range.vue +++ b/packages/components/date-picker-panel/src/date-picker-com/panel-month-range.vue @@ -148,7 +148,8 @@ const unit = 'year' const { lang } = useLocale() const pickerBase = inject(PICKER_BASE_INJECTION_KEY) as any const isDefaultFormat = inject( - ROOT_PICKER_IS_DEFAULT_FORMAT_INJECTION_KEY + ROOT_PICKER_IS_DEFAULT_FORMAT_INJECTION_KEY, + undefined ) as any const { shortcuts, disabledDate } = pickerBase.props const format = toRef(pickerBase.props, 'format') diff --git a/packages/components/date-picker-panel/src/date-picker-com/panel-year-range.vue b/packages/components/date-picker-panel/src/date-picker-com/panel-year-range.vue index 3fe9980da4..de57af059e 100644 --- a/packages/components/date-picker-panel/src/date-picker-com/panel-year-range.vue +++ b/packages/components/date-picker-panel/src/date-picker-com/panel-year-range.vue @@ -133,7 +133,8 @@ const { lang } = useLocale() const leftDate = ref(dayjs().locale(lang.value)) const rightDate = ref(dayjs().locale(lang.value).add(step, unit)) const isDefaultFormat = inject( - ROOT_PICKER_IS_DEFAULT_FORMAT_INJECTION_KEY + ROOT_PICKER_IS_DEFAULT_FORMAT_INJECTION_KEY, + undefined ) as any const pickerBase = inject(PICKER_BASE_INJECTION_KEY) as any const { shortcuts, disabledDate } = pickerBase.props diff --git a/packages/components/date-picker-panel/src/date-picker-panel.tsx b/packages/components/date-picker-panel/src/date-picker-panel.tsx index 33eb68fa51..f770380028 100644 --- a/packages/components/date-picker-panel/src/date-picker-panel.tsx +++ b/packages/components/date-picker-panel/src/date-picker-panel.tsx @@ -1,11 +1,4 @@ -import { - computed, - defineComponent, - inject, - provide, - reactive, - toRefs, -} from 'vue' +import { defineComponent, inject, provide, reactive, toRefs } from 'vue' import dayjs from 'dayjs' import customParseFormat from 'dayjs/plugin/customParseFormat.js' import advancedFormat from 'dayjs/plugin/advancedFormat.js' @@ -16,8 +9,6 @@ import dayOfYear from 'dayjs/plugin/dayOfYear.js' import isSameOrAfter from 'dayjs/plugin/isSameOrAfter.js' import isSameOrBefore from 'dayjs/plugin/isSameOrBefore.js' import { - DEFAULT_FORMATS_DATE, - DEFAULT_FORMATS_DATEPICKER, PICKER_BASE_INJECTION_KEY, ROOT_COMMON_PICKER_INJECTION_KEY, } from '@element-plus/components/time-picker' @@ -25,10 +16,7 @@ import { useNamespace } from '@element-plus/hooks' import { isUndefined } from '@element-plus/utils' import { UPDATE_MODEL_EVENT } from '@element-plus/constants' import { datePickerPanelProps } from './props/date-picker-panel' -import { - ROOT_PICKER_INJECTION_KEY, - ROOT_PICKER_IS_DEFAULT_FORMAT_INJECTION_KEY, -} from './constants' +import { ROOT_PICKER_INJECTION_KEY } from './constants' import { getPanel } from './panel-utils' import { useCommonPicker } from '../../time-picker/src/composables/use-common-picker' @@ -54,27 +42,10 @@ export default defineComponent({ ], setup(props, { slots, emit }) { const ns = useNamespace('picker-panel') - const format = computed( - () => - props.format ?? - (DEFAULT_FORMATS_DATEPICKER[props.type] || DEFAULT_FORMATS_DATE) - ) - - const defaultFormatInjection = inject( - ROOT_PICKER_IS_DEFAULT_FORMAT_INJECTION_KEY, - undefined - ) - if (isUndefined(defaultFormatInjection)) { - const isDefaultFormat = computed(() => { - return !props.format - }) - provide(ROOT_PICKER_IS_DEFAULT_FORMAT_INJECTION_KEY, isDefaultFormat) - } const pickerInjection = inject(PICKER_BASE_INJECTION_KEY, undefined) if (isUndefined(pickerInjection)) { const _props = reactive({ ...toRefs(props), - format, }) provide(PICKER_BASE_INJECTION_KEY, { props: _props, @@ -102,7 +73,6 @@ export default defineComponent({ return ( + defaultFormat: ComputedRef | undefined ): Dayjs | Dayjs[] => { if (isArray(value)) { return value.map( @@ -216,7 +216,9 @@ export const correctlyParseUserInput = ( ) } if (isString(value)) { - const dayjsValue = defaultFormat.value ? dayjs(value) : dayjs(value, format) + const dayjsValue = defaultFormat?.value + ? dayjs(value) + : dayjs(value, format) if (!dayjsValue.isValid()) { // return directly if not valid return dayjsValue diff --git a/packages/components/date-picker/__tests__/date-time-picker.test.tsx b/packages/components/date-picker/__tests__/date-time-picker.test.tsx index 275c7e855a..d900d70800 100644 --- a/packages/components/date-picker/__tests__/date-time-picker.test.tsx +++ b/packages/components/date-picker/__tests__/date-time-picker.test.tsx @@ -131,6 +131,35 @@ describe('Datetime Picker', () => { expect(dayjs(value.value).diff(dayjs()) < 10).toBeTruthy() }) + it("should date input respect the default format 'YYYY-MM-DD' when format with only time format is setted", async () => { + const modelValue = new Date(2000, 10, 10, 10, 10) + const wrapper = mount(() => ( + + )) + + const input = wrapper.find('input') + await input.trigger('blur') + await input.trigger('focus') + const timeInput = document.querySelector( + '.el-date-picker__editor-wrap input' + ) + expect((timeInput as HTMLInputElement).value).toBe('2000-11-10') + }) + + it("should time input respect the default format 'HH:mm:ss' when format with only date format is setted", async () => { + const modelValue = new Date(2000, 10, 10, 10, 10) + const wrapper = mount(() => ( + + )) + const input = wrapper.find('input') + await input.trigger('blur') + await input.trigger('focus') + const timeInput = document.querySelectorAll( + '.el-date-picker__editor-wrap input' + )[1] + expect((timeInput as HTMLInputElement).value).toBe('10:10:00') + }) + it('time-picker select && input time && input date', async () => { const value = ref('') const wrapper = _mount(() => ( @@ -1122,4 +1151,37 @@ describe('Datetimerange', () => { await input.trigger('focus') expect(wrapper.findComponent(CircleClose).exists()).toBe(true) }) + it("should date input respect the default format 'YYYY-MM-DD' when format with only time format is setted", async () => { + const modelValue = [ + new Date(2000, 10, 10, 10, 10), + new Date(2000, 10, 11, 10, 10), + ] + const wrapper = mount(() => ( + + )) + const input = wrapper.find('input') + await input.trigger('blur') + await input.trigger('focus') + const timeInput = document.querySelector( + '.el-date-range-picker__editors-wrap input' + ) + expect((timeInput as HTMLInputElement).value).toBe('2000-11-10') + }) + + it("should time input respect the default format 'HH:mm:ss' when format with only date format is setted", async () => { + const modelValue = [ + new Date(2000, 10, 10, 10, 10), + new Date(2000, 10, 11, 10, 10), + ] + const wrapper = mount(() => ( + + )) + const input = wrapper.find('input') + await input.trigger('blur') + await input.trigger('focus') + const timeInput = document.querySelectorAll( + '.el-date-range-picker__editors-wrap input' + )[1] + expect((timeInput as HTMLInputElement).value).toBe('10:10:00') + }) }) diff --git a/packages/components/time-picker/src/common/props.ts b/packages/components/time-picker/src/common/props.ts index 993a656862..401f09086e 100644 --- a/packages/components/time-picker/src/common/props.ts +++ b/packages/components/time-picker/src/common/props.ts @@ -63,11 +63,11 @@ export const timePickerDefaultProps = buildProps({ */ valueFormat: String, /** - * @description optional, format of the date displayed value in TimePicker's dropdown + * @description optional, format of the date displayed in input's inner panel */ dateFormat: String, /** - * @description optional, format of the time displayed value in TimePicker's dropdown + * @description optional, format of the time displayed in input's inner panel */ timeFormat: String, /**