diff --git a/packages/vant/src/datetime-picker/DatePicker.tsx b/packages/vant/src/datetime-picker/DatePicker.tsx index 621cec848..3bebf8809 100644 --- a/packages/vant/src/datetime-picker/DatePicker.tsx +++ b/packages/vant/src/datetime-picker/DatePicker.tsx @@ -23,6 +23,7 @@ import { getTrueValue, getMonthEndDay, pickerInheritKeys, + proxyPickerMethods, } from './utils'; // Composables @@ -316,7 +317,8 @@ export default defineComponent({ ); useExpose({ - getPicker: () => picker.value, + getPicker: () => + picker.value && proxyPickerMethods(picker.value, updateInnerValue), }); return () => ( diff --git a/packages/vant/src/datetime-picker/TimePicker.tsx b/packages/vant/src/datetime-picker/TimePicker.tsx index d3ecf692c..aac16aec1 100644 --- a/packages/vant/src/datetime-picker/TimePicker.tsx +++ b/packages/vant/src/datetime-picker/TimePicker.tsx @@ -16,7 +16,12 @@ import { createNamespace, makeNumericProp, } from '../utils'; -import { times, sharedProps, pickerInheritKeys } from './utils'; +import { + times, + sharedProps, + pickerInheritKeys, + proxyPickerMethods, +} from './utils'; // Composables import { useExpose } from '../composables/use-expose'; @@ -160,7 +165,8 @@ export default defineComponent({ ); useExpose({ - getPicker: () => picker.value, + getPicker: () => + picker.value && proxyPickerMethods(picker.value, updateInnerValue), }); return () => ( diff --git a/packages/vant/src/datetime-picker/test/__snapshots__/datetime-picker.spec.tsx.snap b/packages/vant/src/datetime-picker/test/__snapshots__/datetime-picker.spec.tsx.snap index 3b614dcc8..c69cff11f 100644 --- a/packages/vant/src/datetime-picker/test/__snapshots__/datetime-picker.spec.tsx.snap +++ b/packages/vant/src/datetime-picker/test/__snapshots__/datetime-picker.spec.tsx.snap @@ -1,22 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`should render title slot correctly 1`] = ` -
- - Custom title - -
-`; - -exports[`time type 1`] = ` +exports[`should render time type correctly 1`] = `
`; + +exports[`should render title slot correctly 1`] = ` +
+ + Custom title + +
+`; diff --git a/packages/vant/src/datetime-picker/test/datetime-picker.spec.tsx b/packages/vant/src/datetime-picker/test/datetime-picker.spec.tsx index 929b4931c..76c0978b5 100644 --- a/packages/vant/src/datetime-picker/test/datetime-picker.spec.tsx +++ b/packages/vant/src/datetime-picker/test/datetime-picker.spec.tsx @@ -3,25 +3,29 @@ import { mount, later } from '../../../test'; import { reactive } from 'vue'; import { useExpose } from '../../composables/use-expose'; -test('confirm & cancel event', () => { +test('should emit confirm event after clicking the confirm button', () => { const onConfirm = jest.fn(); - const onCancel = jest.fn(); - const wrapper = mount(DatetimePicker, { props: { onConfirm, + }, + }); + wrapper.find('.van-picker__confirm').trigger('click'); + expect(onConfirm).toHaveBeenCalledTimes(1); +}); + +test('should emit cancel event after clicking the confirm button', () => { + const onCancel = jest.fn(); + const wrapper = mount(DatetimePicker, { + props: { onCancel, }, }); - - wrapper.find('.van-picker__confirm').trigger('click'); - expect(onConfirm).toHaveBeenCalledTimes(1); - wrapper.find('.van-picker__cancel').trigger('click'); expect(onCancel).toHaveBeenCalledTimes(1); }); -test('time type', () => { +test('should render time type correctly', () => { const wrapper = mount(DatetimePicker, { props: { type: 'time', @@ -33,7 +37,7 @@ test('time type', () => { expect(wrapper.html()).toMatchSnapshot(); }); -test('getPicker method', () => { +test('should allow to call getPicker method', () => { const wrapper = mount(DatetimePicker); expect(wrapper.vm.getPicker()).toBeTruthy(); @@ -86,3 +90,39 @@ test('should emit value correctly when dynamic change min-date', async () => { wrapper.find('.van-picker__confirm').trigger('click'); expect(wrapper.emitted<[Date]>('confirm')![0][0]).toEqual(defaultValue); }); + +test('should update value correctly after calling setColumnIndex method', async () => { + const onConfirm = jest.fn(); + const defaultDate = new Date(2020, 0, 1); + const wrapper = mount(DatetimePicker, { + props: { + type: 'date', + minDate: defaultDate, + maxDate: new Date(2020, 0, 30), + modelValue: defaultDate, + onConfirm, + }, + }); + + wrapper.vm.getPicker().setColumnIndex(2, 14); + await wrapper.find('.van-picker__confirm').trigger('click'); + expect(onConfirm.mock.calls[0]).toEqual([new Date(2020, 0, 15)]); +}); + +test('should update value correctly after calling setColumnValue method', async () => { + const onConfirm = jest.fn(); + const defaultDate = new Date(2020, 0, 1); + const wrapper = mount(DatetimePicker, { + props: { + type: 'date', + minDate: defaultDate, + maxDate: new Date(2020, 0, 30), + modelValue: defaultDate, + onConfirm, + }, + }); + + wrapper.vm.getPicker().setColumnValue(2, '15'); + await wrapper.find('.van-picker__confirm').trigger('click'); + expect(onConfirm.mock.calls[0]).toEqual([new Date(2020, 0, 15)]); +}); diff --git a/packages/vant/src/datetime-picker/utils.ts b/packages/vant/src/datetime-picker/utils.ts index ee09f1387..f78e90d06 100644 --- a/packages/vant/src/datetime-picker/utils.ts +++ b/packages/vant/src/datetime-picker/utils.ts @@ -1,6 +1,7 @@ import { PropType } from 'vue'; import { extend } from '../utils'; import { pickerSharedProps } from '../picker/Picker'; +import type { PickerInstance } from '../picker'; import type { DatetimePickerColumnType } from './types'; export const sharedProps = extend({}, pickerSharedProps, { @@ -45,3 +46,27 @@ export function getTrueValue(value: string | undefined): number { export const getMonthEndDay = (year: number, month: number): number => 32 - new Date(year, month - 1, 32).getDate(); + +// https://github.com/youzan/vant/issues/10013 +export const proxyPickerMethods = ( + picker: PickerInstance, + callback: () => void +) => { + const methods = [ + 'setValues', + 'setIndexes', + 'setColumnIndex', + 'setColumnValue', + ]; + return new Proxy(picker, { + get: (target, prop: keyof PickerInstance) => { + if (methods.includes(prop)) { + return (...args: unknown[]) => { + target[prop](...args); + callback(); + }; + } + return target[prop]; + }, + }); +};