From baa9c33dd43f940e1c21c4f673155579ee91d736 Mon Sep 17 00:00:00 2001 From: neverland Date: Fri, 7 Oct 2022 23:04:56 +0800 Subject: [PATCH] fix(DatePicker): format value when exceed max date (#11122) --- packages/vant/src/date-picker/DatePicker.tsx | 5 + .../date-picker/test/date-picker.legacy.ts | 49 ------- .../vant/src/date-picker/test/index.legacy.ts | 59 --------- .../vant/src/date-picker/test/index.spec.ts | 121 ++++++++++++++++++ packages/vant/src/date-picker/utils.ts | 12 ++ packages/vant/src/time-picker/TimePicker.tsx | 19 ++- 6 files changed, 147 insertions(+), 118 deletions(-) delete mode 100644 packages/vant/src/date-picker/test/index.legacy.ts create mode 100644 packages/vant/src/date-picker/test/index.spec.ts diff --git a/packages/vant/src/date-picker/DatePicker.tsx b/packages/vant/src/date-picker/DatePicker.tsx index e8bfdaeaf..f0c0256cc 100644 --- a/packages/vant/src/date-picker/DatePicker.tsx +++ b/packages/vant/src/date-picker/DatePicker.tsx @@ -14,6 +14,7 @@ import { sharedProps, getMonthEndDay, pickerInheritKeys, + formatValueRange, } from './utils'; // Components @@ -143,9 +144,13 @@ export default defineComponent({ watch( () => props.modelValue, (newValues) => { + newValues = formatValueRange(newValues, columns.value); if (!isSameValue(newValues, currentValues.value)) { currentValues.value = newValues; } + }, + { + immediate: true, } ); diff --git a/packages/vant/src/date-picker/test/date-picker.legacy.ts b/packages/vant/src/date-picker/test/date-picker.legacy.ts index a4dff6036..0bb6c36c8 100644 --- a/packages/vant/src/date-picker/test/date-picker.legacy.ts +++ b/packages/vant/src/date-picker/test/date-picker.legacy.ts @@ -143,55 +143,6 @@ // expect(wrapper.emitted<[Date]>('confirm')![1][0].getHours()).toEqual(23); // }); -// test('cancel event', () => { -// const wrapper = mount(DatePicker); - -// wrapper.find('.van-picker__cancel').trigger('click'); -// expect(wrapper.emitted('cancel')).toBeTruthy(); -// }); - -// test('max-date prop', () => { -// const maxDate = new Date(2010, 5, 0, 0, 0); -// const wrapper = mount(DatePicker, { -// props: { -// modelValue: new Date(2020, 10, 30, 30, 30), -// maxDate, -// }, -// }); - -// wrapper.find('.van-picker__confirm').trigger('click'); -// expect(wrapper.emitted<[Date]>('confirm')![0][0]).toEqual(maxDate); -// }); - -// test('min-date prop', () => { -// const minDate = new Date(2030, 0, 0, 0, 0); -// const wrapper = mount(DatePicker, { -// props: { -// modelValue: new Date(2020, 0, 0, 0, 0), -// minDate, -// }, -// }); - -// wrapper.find('.van-picker__confirm').trigger('click'); -// expect(wrapper.emitted<[Date]>('confirm')![0][0]).toEqual(minDate); -// }); - -// test('dynamic set value', async () => { -// const wrapper = mount(DatePicker, { -// props: { -// modelValue: new Date(2019, 1, 1), -// }, -// }); - -// await wrapper.setProps({ modelValue: new Date(2019, 1, 1) }); -// wrapper.find('.van-picker__confirm').trigger('click'); -// await wrapper.setProps({ modelValue: new Date(2025, 1, 1) }); -// wrapper.find('.van-picker__confirm').trigger('click'); - -// expect(wrapper.emitted<[Date]>('confirm')![0][0].getFullYear()).toEqual(2019); -// expect(wrapper.emitted<[Date]>('confirm')![1][0].getFullYear()).toEqual(2025); -// }); - // test('use min-date with filter', async () => { // const minDate = new Date(2030, 0, 0, 0, 3); // const maxDate = new Date(2040, 0, 0, 0, 0); diff --git a/packages/vant/src/date-picker/test/index.legacy.ts b/packages/vant/src/date-picker/test/index.legacy.ts deleted file mode 100644 index f490ec9c2..000000000 --- a/packages/vant/src/date-picker/test/index.legacy.ts +++ /dev/null @@ -1,59 +0,0 @@ -// import { later, mount, triggerDrag } from '../../../test'; -// import DatePicker from '../../datetime-picker/DatePicker'; - -// test('month-day type', async () => { -// const date = new Date(2020, 10, 1, 0, 0); - -// const wrapper = mount(DatePicker, { -// props: { -// type: 'month-day', -// modelValue: date, -// minDate: new Date(2020, 0, 1), -// maxDate: new Date(2025, 10, 1), -// }, -// }); - -// await later(); -// wrapper.find('.van-picker__confirm').trigger('click'); -// expect(wrapper.emitted<[Date]>('confirm')![0][0].getMonth()).toEqual(10); -// expect(wrapper.emitted<[Date]>('confirm')![0][0].getDate()).toEqual(1); - -// await later(); -// triggerDrag(wrapper.find('.van-picker-column'), 0, -300); -// wrapper.find('.van-picker__confirm').trigger('click'); -// expect(wrapper.emitted<[Date]>('confirm')![1][0].getMonth()).toEqual(11); -// expect(wrapper.emitted<[Date]>('confirm')![1][0].getDate()).toEqual(1); - -// await later(); -// triggerDrag(wrapper.findAll('.van-picker-column')[1], 0, -300); -// wrapper.find('.van-picker__confirm').trigger('click'); -// expect(wrapper.emitted<[Date]>('confirm')![2][0].getMonth()).toEqual(11); -// expect(wrapper.emitted<[Date]>('confirm')![2][0].getDate()).toEqual(31); -// }); - -// test('v-model', async () => { -// const minDate = new Date(2030, 0, 0, 0, 3); - -// const wrapper = mount(DatePicker, { -// props: { -// minDate, -// }, -// }); - -// await later(); -// wrapper.find('.van-picker__confirm').trigger('click'); -// expect(wrapper.emitted<[Date]>('confirm')![0][0]).toEqual(minDate); -// }); - -// test('value has an initial value', async () => { -// const defaultValue = new Date(2020, 0, 0, 0, 0); -// const wrapper = mount(DatePicker, { -// propsData: { -// modelValue: defaultValue, -// }, -// }); - -// await later(); -// wrapper.find('.van-picker__confirm').trigger('click'); -// expect(wrapper.emitted<[Date]>('confirm')![0][0]).toEqual(defaultValue); -// }); diff --git a/packages/vant/src/date-picker/test/index.spec.ts b/packages/vant/src/date-picker/test/index.spec.ts new file mode 100644 index 000000000..395c44e82 --- /dev/null +++ b/packages/vant/src/date-picker/test/index.spec.ts @@ -0,0 +1,121 @@ +import { nextTick } from 'vue'; +import { later, mount } from '../../../test'; +import DatePicker from '..'; +import type { + PickerCancelEventParams, + PickerConfirmEventParams, +} from '../../picker'; + +test('should emit confirm event correctly', async () => { + const minDate = new Date(2030, 0, 1); + + const wrapper = mount(DatePicker, { + props: { + minDate, + }, + }); + + await later(); + wrapper.find('.van-picker__confirm').trigger('click'); + expect(wrapper.emitted<[PickerConfirmEventParams]>('confirm')![0][0]).toEqual( + { + selectedOptions: [ + { text: '2030', value: '2030' }, + { text: '01', value: '01' }, + { text: '01', value: '01' }, + ], + selectedValues: ['2030', '01', '01'], + } + ); +}); + +test('should emit cancel event correctly', async () => { + const minDate = new Date(2030, 0, 1); + const wrapper = mount(DatePicker, { + props: { + minDate, + }, + }); + + await later(); + wrapper.find('.van-picker__cancel').trigger('click'); + expect(wrapper.emitted<[PickerCancelEventParams]>('cancel')![0][0]).toEqual({ + selectedOptions: [ + { text: '2030', value: '2030' }, + { text: '01', value: '01' }, + { text: '01', value: '01' }, + ], + selectedValues: ['2030', '01', '01'], + }); +}); + +test('should allow to dynamically set value', async () => { + const wrapper = mount(DatePicker, { + props: { + modelValue: ['2020', '01', '01'], + minDate: new Date(2019, 0, 1), + }, + }); + + await wrapper.setProps({ modelValue: ['2020', '02', '02'] }); + await wrapper.find('.van-picker__confirm').trigger('click'); + await wrapper.setProps({ modelValue: ['2020', '03', '03'] }); + await wrapper.find('.van-picker__confirm').trigger('click'); + + expect( + wrapper.emitted<[PickerConfirmEventParams]>('confirm')![0][0].selectedValues + ).toEqual(['2020', '02', '02']); + expect( + wrapper.emitted<[PickerConfirmEventParams]>('confirm')![1][0].selectedValues + ).toEqual(['2020', '03', '03']); +}); + +test('should render with max-date correctly', async () => { + const maxDate = new Date(2010, 1, 1); + const minDate = new Date(2000, 1, 1); + const wrapper = mount(DatePicker, { + props: { + modelValue: ['2020', '10', '10'], + minDate, + maxDate, + 'onUpdate:modelValue': (newVal: string[]) => { + nextTick(() => { + wrapper.setProps({ + modelValue: newVal, + }); + }); + }, + }, + }); + + await later(); + wrapper.find('.van-picker__confirm').trigger('click'); + expect( + wrapper.emitted<[PickerConfirmEventParams]>('confirm')![0][0].selectedValues + ).toEqual(['2010', '01', '10']); +}); + +test('should render with min-date correctly', async () => { + const maxDate = new Date(2010, 1, 1); + const minDate = new Date(2000, 1, 1); + const wrapper = mount(DatePicker, { + props: { + modelValue: ['1990', '10', '10'], + minDate, + maxDate, + 'onUpdate:modelValue': (newVal: string[]) => { + nextTick(() => { + wrapper.setProps({ + modelValue: newVal, + }); + }); + }, + }, + }); + + await later(); + wrapper.find('.van-picker__confirm').trigger('click'); + expect( + wrapper.emitted<[PickerConfirmEventParams]>('confirm')![0][0].selectedValues + ).toEqual(['2000', '10', '10']); +}); diff --git a/packages/vant/src/date-picker/utils.ts b/packages/vant/src/date-picker/utils.ts index adc119817..28960a1e7 100644 --- a/packages/vant/src/date-picker/utils.ts +++ b/packages/vant/src/date-picker/utils.ts @@ -53,3 +53,15 @@ export const genOptions = ( }); return filter ? filter(type, options) : options; }; + +export const formatValueRange = (values: string[], columns: PickerOption[]) => + values.map((value, index) => { + const column = columns[index]; + if (column.length) { + const maxValue = +column[column.length - 1].value!; + if (+value > maxValue) { + return String(maxValue); + } + } + return value; + }); diff --git a/packages/vant/src/time-picker/TimePicker.tsx b/packages/vant/src/time-picker/TimePicker.tsx index 397c601b5..d754c7a62 100644 --- a/packages/vant/src/time-picker/TimePicker.tsx +++ b/packages/vant/src/time-picker/TimePicker.tsx @@ -19,6 +19,7 @@ import { genOptions, sharedProps, pickerInheritKeys, + formatValueRange, } from '../date-picker/utils'; // Components @@ -89,23 +90,21 @@ export default defineComponent({ }) ); - watch( - currentValues, - (newValues) => { - if (!isSameValue(newValues, props.modelValue)) { - emit('update:modelValue', newValues); - } - }, - { immediate: true } - ); + watch(currentValues, (newValues) => { + if (!isSameValue(newValues, props.modelValue)) { + emit('update:modelValue', newValues); + } + }); watch( () => props.modelValue, (newValues) => { + newValues = formatValueRange(newValues, columns.value); if (!isSameValue(newValues, currentValues.value)) { currentValues.value = newValues; } - } + }, + { immediate: true } ); const onChange = (...args: unknown[]) => emit('change', ...args);