Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(switch): support beforeChange API #4699

Merged
merged 6 commits into from
Nov 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions src/switch/__tests__/base.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -136,5 +136,44 @@ describe('switch', () => {
expect(eleCls.includes('t-size-s')).toBe(true);
});
});
// test props beforeChange
describe(':props.beforeChange', () => {
it('beforeChange resolve', async () => {
const beforeChangeResolve = () =>
new Promise((resolve) => {
setTimeout(() => {
resolve(true);
}, 80);
});
const wrapper = mount({
render() {
return <Switch defaultValue={true} beforeChange={beforeChangeResolve} />;
},
});
wrapper.trigger('click');
await new Promise((resolve) => setTimeout(resolve, 100));
const ele = wrapper.find('.t-switch');
const eleCls = ele.classes();
expect(eleCls.includes('t-is-checked')).toBeFalsy();
});
it('beforeChange reject', async () => {
const beforeChangeReject = () =>
new Promise((_resolve, reject) => {
setTimeout(() => {
reject(new Error('reject'));
}, 80);
}).catch(() => {});
const wrapper = mount({
render() {
return <Switch defaultValue={false} beforeChange={beforeChangeReject} />;
},
});
wrapper.trigger('click');
await new Promise((resolve) => setTimeout(resolve, 100));
const ele = wrapper.find('.t-switch');
const eleCls = ele.classes();
expect(eleCls.includes('t-is-checked')).toBe(false);
});
});
});
});
53 changes: 53 additions & 0 deletions src/switch/_example/before-change.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<template>
<t-space>
<t-switch
v-model="resolveChecked"
:loading="loadingResolve"
:before-change="beforeChangeResolve"
@change="onChangeResolve"
/>
<t-switch
v-model="rejectChecked"
:loading="loadingReject"
:before-change="beforeChangeReject"
@change="onChangeReject"
/>
</t-space>
</template>

<script setup>
import { ref } from 'vue';

const resolveChecked = ref(true);
const rejectChecked = ref(true);
const loadingResolve = ref(false);
const loadingReject = ref(false);

const onChangeResolve = (v) => {
console.log(v);
};

const onChangeReject = (v) => {
console.log(v);
};

const beforeChangeResolve = () => {
loadingResolve.value = true;
return new Promise((resolve) => {
setTimeout(() => {
loadingResolve.value = false;
resolve(true);
}, 1000);
});
};

const beforeChangeReject = () => {
loadingReject.value = true;
return new Promise((_resolve, reject) => {
setTimeout(() => {
loadingReject.value = false;
reject(new Error('reject'));
}, 1000);
});
};
</script>
4 changes: 4 additions & 0 deletions src/switch/props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ import { TdSwitchProps } from './type';
import { PropType } from 'vue';

export default {
/** Switch 切换状态前的回调方法,常用于需要发起异步请求的场景,回调返回值支持布尔和 Promise 类型,返回`false`或 Promise reject不继续执行change,否则则继续执行。 */
beforeChange: {
type: Function as PropType<TdSwitchProps['beforeChange']>,
},
/** 用于自定义开关的值,[打开时的值,关闭时的值]。默认为 [true, false]。示例:[1, 0]、['open', 'close'] */
customValue: {
type: Array as PropType<TdSwitchProps['customValue']>,
Expand Down
1 change: 1 addition & 0 deletions src/switch/switch.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

name | type | default | description | required
-- | -- | -- | -- | --
beforeChange | Function | - | stop checked change。Typescript:`() => boolean \| Promise<boolean>` | N
customValue | Array | - | Typescript:`Array<SwitchValue>` | N
disabled | Boolean | undefined | \- | N
label | Array / Slot / Function | [] | Typescript:`Array<string \| TNode> \| TNode<{ value: SwitchValue }>`。[see more ts definition](https://github.com/Tencent/tdesign-vue-next/blob/develop/src/common.ts) | N
Expand Down
1 change: 1 addition & 0 deletions src/switch/switch.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

名称 | 类型 | 默认值 | 说明 | 必传
-- | -- | -- | -- | --
beforeChange | Function | - | Switch 切换状态前的回调方法,常用于需要发起异步请求的场景,回调返回值支持布尔和 Promise 类型,返回`false`或 Promise reject不继续执行change,否则则继续执行。。TS 类型:`() => boolean \| Promise<boolean>` | N
customValue | Array | - | 用于自定义开关的值,[打开时的值,关闭时的值]。默认为 [true, false]。示例:[1, 0]、['open', 'close']。TS 类型:`Array<SwitchValue>` | N
disabled | Boolean | undefined | 是否禁用组件。优先级:Switch.disabled > Form.disabled | N
label | Array / Slot / Function | [] | 开关内容,[开启时内容,关闭时内容]。示例:['开', '关'] 或 (value) => value ? '开' : '关'。TS 类型:`Array<string \| TNode> \| TNode<{ value: SwitchValue }>`。[通用类型定义](https://github.com/Tencent/tdesign-vue-next/blob/develop/src/common.ts) | N
Expand Down
14 changes: 13 additions & 1 deletion src/switch/switch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,19 @@ export default defineComponent({
if (disabled.value || props.loading) {
return;
}
handleToggle(e);
if (!props.beforeChange) {
handleToggle(e);
return;
}
Promise.resolve(props.beforeChange())
.then((v) => {
if (v) {
handleToggle(e);
}
})
.catch((e) => {
throw new Error(`Switch: some error occurred: ${e}`);
});
}

// classes
Expand Down
4 changes: 4 additions & 0 deletions src/switch/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
import { TNode } from '../common';

export interface TdSwitchProps<T = SwitchValue> {
/**
* Switch 切换状态前的回调方法,常用于需要发起异步请求的场景,回调返回值支持布尔和 Promise 类型,返回`false`或 Promise reject不继续执行change,否则则继续执行。
*/
beforeChange?: () => boolean | Promise<boolean>;
/**
* 用于自定义开关的值,[打开时的值,关闭时的值]。默认为 [true, false]。示例:[1, 0]、['open', 'close']
*/
Expand Down
54 changes: 54 additions & 0 deletions test/unit/snap/__snapshots__/csr.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -124077,6 +124077,60 @@ exports[`csr snapshot test > csr test ./src/switch/_example/base.vue 1`] = `
<!---->


</div>
`;

exports[`csr snapshot test > csr test ./src/switch/_example/before-change.vue 1`] = `
<div
class="t-space t-space-horizontal"
style="gap: 16px;"
>


<div
class="t-space-item"
>
<div
class="t-switch t-size-m t-is-checked"
disabled="false"
>
<span
class="t-switch__handle"
>
<!---->
</span>
<div
class="t-switch__content t-size-m"
>
<!---->
</div>
</div>
</div>
<!---->


<div
class="t-space-item"
>
<div
class="t-switch t-size-m t-is-checked"
disabled="false"
>
<span
class="t-switch__handle"
>
<!---->
</span>
<div
class="t-switch__content t-size-m"
>
<!---->
</div>
</div>
</div>
<!---->


</div>
`;

Expand Down
2 changes: 2 additions & 0 deletions test/unit/snap/__snapshots__/ssr.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -1018,6 +1018,8 @@ exports[`ssr snapshot test > ssr test ./src/swiper/_example/vertical.vue 1`] = `

exports[`ssr snapshot test > ssr test ./src/switch/_example/base.vue 1`] = `"<div class=\\"t-space t-space-horizontal\\" style=\\"gap:16px;\\"><!--[--><!--[--><div class=\\"t-space-item\\"><div class=\\"t-switch t-size-m\\"><span class=\\"t-switch__handle\\"><!----></span><div class=\\"t-switch__content t-size-m\\"><!----></div></div></div><!----><!--]--><!--[--><div class=\\"t-space-item\\"><div class=\\"t-switch t-size-m t-is-checked\\"><span class=\\"t-switch__handle\\"><!----></span><div class=\\"t-switch__content t-size-m\\"><!----></div></div></div><!----><!--]--><!--]--></div>"`;

exports[`ssr snapshot test > ssr test ./src/switch/_example/before-change.vue 1`] = `"<div class=\\"t-space t-space-horizontal\\" style=\\"gap:16px;\\"><!--[--><!--[--><div class=\\"t-space-item\\"><div class=\\"t-switch t-size-m t-is-checked\\"><span class=\\"t-switch__handle\\"><!----></span><div class=\\"t-switch__content t-size-m\\"><!----></div></div></div><!----><!--]--><!--[--><div class=\\"t-space-item\\"><div class=\\"t-switch t-size-m t-is-checked\\"><span class=\\"t-switch__handle\\"><!----></span><div class=\\"t-switch__content t-size-m\\"><!----></div></div></div><!----><!--]--><!--]--></div>"`;

exports[`ssr snapshot test > ssr test ./src/switch/_example/describe.vue 1`] = `"<div class=\\"t-space t-space-vertical\\" style=\\"gap:16px;\\" data-v-0e67a2ed><!--[--><!--[--><div class=\\"t-space-item\\"><div class=\\"t-space t-space-horizontal\\" style=\\"gap:16px;\\" data-v-0e67a2ed><!--[--><!--[--><div class=\\"t-space-item\\"><div class=\\"t-switch t-size-l t-is-checked\\" data-v-0e67a2ed><span class=\\"t-switch__handle\\"><!----></span><div class=\\"t-switch__content t-size-l\\"><!--[-->开<!--]--></div></div></div><!----><!--]--><!--[--><div class=\\"t-space-item\\"><div class=\\"t-switch t-size-l\\" data-v-0e67a2ed><span class=\\"t-switch__handle\\"><!----></span><div class=\\"t-switch__content t-size-l\\"><!--[--><svg fill=\\"none\\" viewBox=\\"0 0 24 24\\" width=\\"1em\\" height=\\"1em\\" class=\\"t-icon t-icon-close\\" style=\\"\\" data-v-0e67a2ed><path fill=\\"currentColor\\" d=\\"M7.05 5.64L12 10.59l4.95-4.95 1.41 1.41L13.41 12l4.95 4.95-1.41 1.41L12 13.41l-4.95 4.95-1.41-1.41L10.59 12 5.64 7.05l1.41-1.41z\\"></path></svg><!--]--></div></div></div><!----><!--]--><!--]--></div></div><!----><!--]--><!--[--><div class=\\"t-space-item\\"><div class=\\"t-space t-space-horizontal\\" style=\\"gap:16px;\\" data-v-0e67a2ed><!--[--><!--[--><div class=\\"t-space-item\\"><div class=\\"t-switch t-size-l t-is-checked\\" data-v-0e67a2ed><span class=\\"t-switch__handle\\"><!----></span><div class=\\"t-switch__content t-size-l\\">开</div></div></div><!----><!--]--><!--[--><div class=\\"t-space-item\\"><div class=\\"t-switch t-size-l\\" data-v-0e67a2ed><span class=\\"t-switch__handle\\"><!----></span><div class=\\"t-switch__content t-size-l\\">关</div></div></div><!----><!--]--><!--]--></div></div><!----><!--]--><!--[--><div class=\\"t-space-item\\"><div class=\\"t-space t-space-horizontal\\" style=\\"gap:16px;\\" data-v-0e67a2ed><!--[--><!--[--><div class=\\"t-space-item\\"><div class=\\"t-switch t-size-l t-is-checked\\" data-v-0e67a2ed><span class=\\"t-switch__handle\\"><!----></span><div class=\\"t-switch__content t-size-l\\"><svg fill=\\"none\\" viewBox=\\"0 0 24 24\\" width=\\"1em\\" height=\\"1em\\" class=\\"t-icon t-icon-check\\" style=\\"\\"><path fill=\\"currentColor\\" d=\\"M20.99 7.38l-10.61 10.6L4 11.63l1.42-1.41 4.95 4.95 9.2-9.2 1.4 1.42z\\"></path></svg></div></div></div><!----><!--]--><!--[--><div class=\\"t-space-item\\"><div class=\\"t-switch t-size-l\\" data-v-0e67a2ed><span class=\\"t-switch__handle\\"><!----></span><div class=\\"t-switch__content t-size-l\\"><svg fill=\\"none\\" viewBox=\\"0 0 24 24\\" width=\\"1em\\" height=\\"1em\\" class=\\"t-icon t-icon-close\\" style=\\"\\"><path fill=\\"currentColor\\" d=\\"M7.05 5.64L12 10.59l4.95-4.95 1.41 1.41L13.41 12l4.95 4.95-1.41 1.41L12 13.41l-4.95 4.95-1.41-1.41L10.59 12 5.64 7.05l1.41-1.41z\\"></path></svg></div></div></div><!----><!--]--><!--]--></div></div><!----><!--]--><!--[--><div class=\\"t-space-item\\"><div class=\\"t-space t-space-horizontal\\" style=\\"gap:16px;\\" data-v-0e67a2ed><!--[--><!--[--><div class=\\"t-space-item\\"><div class=\\"t-switch t-size-l t-is-checked\\" data-v-0e67a2ed><span class=\\"t-switch__handle\\"><!----></span><div class=\\"t-switch__content t-size-l\\"><svg fill=\\"none\\" viewBox=\\"0 0 24 24\\" width=\\"1em\\" height=\\"1em\\" class=\\"t-icon t-icon-check\\" style=\\"\\"><path fill=\\"currentColor\\" d=\\"M20.99 7.38l-10.61 10.6L4 11.63l1.42-1.41 4.95 4.95 9.2-9.2 1.4 1.42z\\"></path></svg></div></div></div><!----><!--]--><!--[--><div class=\\"t-space-item\\"><div class=\\"t-switch t-size-l\\" data-v-0e67a2ed><span class=\\"t-switch__handle\\"><!----></span><div class=\\"t-switch__content t-size-l\\"><svg fill=\\"none\\" viewBox=\\"0 0 24 24\\" width=\\"1em\\" height=\\"1em\\" class=\\"t-icon t-icon-close\\" style=\\"\\"><path fill=\\"currentColor\\" d=\\"M7.05 5.64L12 10.59l4.95-4.95 1.41 1.41L13.41 12l4.95 4.95-1.41 1.41L12 13.41l-4.95 4.95-1.41-1.41L10.59 12 5.64 7.05l1.41-1.41z\\"></path></svg></div></div></div><!----><!--]--><!--]--></div></div><!----><!--]--><!--]--></div>"`;

exports[`ssr snapshot test > ssr test ./src/switch/_example/size.vue 1`] = `"<div class=\\"t-space t-space-horizontal\\" style=\\"gap:16px;\\"><!--[--><!--[--><div class=\\"t-space-item\\"><div class=\\"t-switch t-size-l t-is-checked\\"><span class=\\"t-switch__handle\\"><!----></span><div class=\\"t-switch__content t-size-l\\"><!----></div></div></div><!----><!--]--><!--[--><div class=\\"t-space-item\\"><div class=\\"t-switch t-size-m\\"><span class=\\"t-switch__handle\\"><!----></span><div class=\\"t-switch__content t-size-m\\"><!----></div></div></div><!----><!--]--><!--[--><div class=\\"t-space-item\\"><div class=\\"t-switch t-size-s\\"><span class=\\"t-switch__handle\\"><!----></span><div class=\\"t-switch__content t-size-s\\"><!----></div></div></div><!----><!--]--><!--]--></div>"`;
Expand Down
Loading