diff --git a/packages/vant/src/picker-group/PickerGroup.tsx b/packages/vant/src/picker-group/PickerGroup.tsx index 812fd44cf..2c0559d97 100644 --- a/packages/vant/src/picker-group/PickerGroup.tsx +++ b/packages/vant/src/picker-group/PickerGroup.tsx @@ -1,4 +1,9 @@ -import { defineComponent, type InjectionKey, type ExtractPropTypes } from 'vue'; +import { + ref, + defineComponent, + type InjectionKey, + type ExtractPropTypes, +} from 'vue'; // Utils import { extend, makeArrayProp, createNamespace } from '../utils'; @@ -20,6 +25,7 @@ export const PICKER_GROUP_KEY: InjectionKey = Symbol(name); export const pickerGroupProps = extend( { tabs: makeArrayProp(), + nextStepText: String, }, pickerToolbarProps ); @@ -34,26 +40,47 @@ export default defineComponent({ emits: ['confirm', 'cancel'], setup(props, { emit, slots }) { + const activeTab = ref(0); const { children, linkChildren } = useChildren(PICKER_GROUP_KEY); linkChildren(); + const showNextButton = () => + activeTab.value < props.tabs.length - 1 && props.nextStepText; + const onConfirm = () => { - emit( - 'confirm', - children.map((item) => item.confirm()) - ); + if (showNextButton()) { + activeTab.value++; + } else { + emit( + 'confirm', + children.map((item) => item.confirm()) + ); + } }; const onCancel = () => emit('cancel'); return () => { const childNodes = slots.default?.(); + const confirmButtonText = showNextButton() + ? props.nextStepText + : props.confirmButtonText; return (
- - + + {props.tabs.map((title, index) => ( {childNodes?.[index]} diff --git a/packages/vant/src/picker-group/README.md b/packages/vant/src/picker-group/README.md index 667cca2b4..4e94a730f 100644 --- a/packages/vant/src/picker-group/README.md +++ b/packages/vant/src/picker-group/README.md @@ -75,6 +75,54 @@ export default { }; ``` +### Next Step Button + +In some scenarios, in order to ensure that users can select all Pickers in turn, you can set the `next-step-text` prop of PickerGroup. After setting the `next-step-text` prop, if the user has not switched to the last tab, the button in the upper right corner will become "Next Step", and automatically switch to the next Picker after clicking. When the user switches to the last tab, the button in the upper right corner changes to "Confirm". + +```html + + + + +``` + +```js +import { ref } from 'vue'; +import { showToast } from 'vant'; + +export default { + setup() { + const currentDate = ref(['2022', '06', '01']); + const currentTime = ref(['12', '00']); + const onConfirm = () => { + showToast( + `${currentDate.value.join('/')} ${currentTime.value.join(':')}` + ); + }; + const onCancel = () => { + showToast('cancel'); + }; + + return { + minDate: new Date(2020, 0, 1), + maxDate: new Date(2025, 5, 1), + currentDate, + currentTime, + }; + }, +}; +``` + ### Select Date Range Place two `DatePicker` components in the default slot of `PickerGroup` to select the time range. @@ -165,12 +213,13 @@ export default { ### Props -| Attribute | Description | Type | Default | -| ------------------- | ---------------------- | ---------- | --------- | -| tabs | Titles of tabs | _string[]_ | `[]` | -| title | Toolbar title | _string_ | `''` | -| confirm-button-text | Text of confirm button | _string_ | `Confirm` | -| cancel-button-text | Text of cancel button | _string_ | `Cancel` | +| Attribute | Description | Type | Default | +| ------------------- | ------------------------ | ---------- | --------- | +| tabs | Titles of tabs | _string[]_ | `[]` | +| title | Toolbar title | _string_ | `''` | +| next-step-text | Text of next step button | _string_ | `''` | +| confirm-button-text | Text of confirm button | _string_ | `Confirm` | +| cancel-button-text | Text of cancel button | _string_ | `Cancel` | ### Slots diff --git a/packages/vant/src/picker-group/README.zh-CN.md b/packages/vant/src/picker-group/README.zh-CN.md index 102ac1fd8..9775ab510 100644 --- a/packages/vant/src/picker-group/README.zh-CN.md +++ b/packages/vant/src/picker-group/README.zh-CN.md @@ -75,6 +75,54 @@ export default { }; ``` +### 下一步按钮 + +部分场景下,为了保证用户能够依次选择所有的 Picker,你可以设置 PickerGroup 的 `next-step-text` 属性。在设置 `next-step-text` 属性后,如果用户未切换到最后一个标签页,那么右上角的按钮会变成「下一步」,点击后自动切换到下一个 Picker。当用户切换到最后一个标签页时,右上角的按钮会变为「确认」。 + +```html + + + + +``` + +```js +import { ref } from 'vue'; +import { showToast } from 'vant'; + +export default { + setup() { + const currentDate = ref(['2022', '06', '01']); + const currentTime = ref(['12', '00']); + const onConfirm = () => { + showToast( + `${currentDate.value.join('/')} ${currentTime.value.join(':')}` + ); + }; + const onCancel = () => { + showToast('cancel'); + }; + + return { + minDate: new Date(2020, 0, 1), + maxDate: new Date(2025, 5, 1), + currentDate, + currentTime, + }; + }, +}; +``` + ### 选择日期范围 在 `PickerGroup` 的默认插槽中放置两个 `DatePicker` 组件,可以实现选择日期范围的交互效果。 @@ -169,8 +217,9 @@ export default { | ------------------- | ---------------- | ---------- | ------ | | tabs | 设置标签页的标题 | _string[]_ | `[]` | | title | 顶部栏标题 | _string_ | `''` | -| confirm-button-text | 确认按钮文字 | _string_ | `确认` | -| cancel-button-text | 取消按钮文字 | _string_ | `取消` | +| next-step-text | 下一步按钮的文字 | _string_ | `''` | +| confirm-button-text | 确认按钮的文字 | _string_ | `确认` | +| cancel-button-text | 取消按钮的文字 | _string_ | `取消` | ### Slots diff --git a/packages/vant/src/picker-group/demo/NextStepButton.vue b/packages/vant/src/picker-group/demo/NextStepButton.vue new file mode 100644 index 000000000..48127cd73 --- /dev/null +++ b/packages/vant/src/picker-group/demo/NextStepButton.vue @@ -0,0 +1,52 @@ + + + diff --git a/packages/vant/src/picker-group/demo/index.vue b/packages/vant/src/picker-group/demo/index.vue index 29133dd8d..8bde31f55 100644 --- a/packages/vant/src/picker-group/demo/index.vue +++ b/packages/vant/src/picker-group/demo/index.vue @@ -2,6 +2,7 @@ import SelectDateTime from './SelectDateTime.vue'; import SelectTimeRange from './SelectTimeRange.vue'; import SelectDateRange from './SelectDateRange.vue'; +import NextStepButton from './NextStepButton.vue'; import { useTranslate } from '../../../docs/site'; const t = useTranslate({ @@ -9,11 +10,13 @@ const t = useTranslate({ selectDateTime: '选择日期时间', selectDateRange: '选择日期范围', selectTimeRange: '选择时间范围', + nextStepButton: '下一步按钮', }, 'en-US': { selectDateTime: 'Select Date Time', selectDateRange: 'Select Date Range', selectTimeRange: 'Select Time Range', + nextStepButton: 'Next Step Button', }, }); @@ -23,6 +26,10 @@ const t = useTranslate({ + + + + diff --git a/packages/vant/src/picker-group/test/__snapshots__/demo.spec.ts.snap b/packages/vant/src/picker-group/test/__snapshots__/demo.spec.ts.snap index 0493b9891..58ddaa3b5 100644 --- a/packages/vant/src/picker-group/test/__snapshots__/demo.spec.ts.snap +++ b/packages/vant/src/picker-group/test/__snapshots__/demo.spec.ts.snap @@ -1331,6 +1331,1337 @@ exports[`should render demo and match snapshot 1`] = `
+
+
+
+ +
+ Title +
+ +
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+
+
+
    +
  • +
    + 2020 +
    +
  • +
  • +
    + 2021 +
    +
  • +
  • +
    + 2022 +
    +
  • +
  • +
    + 2023 +
    +
  • +
  • +
    + 2024 +
    +
  • +
  • +
    + 2025 +
    +
  • +
+
+
+
    +
  • +
    + 01 +
    +
  • +
  • +
    + 02 +
    +
  • +
  • +
    + 03 +
    +
  • +
  • +
    + 04 +
    +
  • +
  • +
    + 05 +
    +
  • +
  • +
    + 06 +
    +
  • +
  • +
    + 07 +
    +
  • +
  • +
    + 08 +
    +
  • +
  • +
    + 09 +
    +
  • +
  • +
    + 10 +
    +
  • +
  • +
    + 11 +
    +
  • +
  • +
    + 12 +
    +
  • +
+
+
+
    +
  • +
    + 01 +
    +
  • +
  • +
    + 02 +
    +
  • +
  • +
    + 03 +
    +
  • +
  • +
    + 04 +
    +
  • +
  • +
    + 05 +
    +
  • +
  • +
    + 06 +
    +
  • +
  • +
    + 07 +
    +
  • +
  • +
    + 08 +
    +
  • +
  • +
    + 09 +
    +
  • +
  • +
    + 10 +
    +
  • +
  • +
    + 11 +
    +
  • +
  • +
    + 12 +
    +
  • +
  • +
    + 13 +
    +
  • +
  • +
    + 14 +
    +
  • +
  • +
    + 15 +
    +
  • +
  • +
    + 16 +
    +
  • +
  • +
    + 17 +
    +
  • +
  • +
    + 18 +
    +
  • +
  • +
    + 19 +
    +
  • +
  • +
    + 20 +
    +
  • +
  • +
    + 21 +
    +
  • +
  • +
    + 22 +
    +
  • +
  • +
    + 23 +
    +
  • +
  • +
    + 24 +
    +
  • +
  • +
    + 25 +
    +
  • +
  • +
    + 26 +
    +
  • +
  • +
    + 27 +
    +
  • +
  • +
    + 28 +
    +
  • +
  • +
    + 29 +
    +
  • +
  • +
    + 30 +
    +
  • +
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
{ + const value1 = ref(['1']); + const value2 = ref(['2']); + + const wrapper = mount({ + setup(props, { emit }) { + const onConfirm = (params: PickerConfirmEventParams) => { + emit('confirm', params); + }; + + return () => ( + + + + + ); + }, + }); + + await wrapper.find('.van-picker__confirm').trigger('click'); + expect(wrapper.emitted('confirm')).toBeFalsy(); + + await wrapper.find('.van-picker__confirm').trigger('click'); + expect(wrapper.emitted('confirm')![0]).toEqual([ + [ + { + selectedIndexes: [0], + selectedOptions: [{ text: '1', value: '1' }], + selectedValues: ['1'], + }, + { + selectedIndexes: [0], + selectedOptions: [{ text: '2', value: '2' }], + selectedValues: ['2'], + }, + ], + ]); +});