Skip to content

Commit

Permalink
feat(switch): support beforeChange API (#4699)
Browse files Browse the repository at this point in the history
* feat(switch): support beforeChange API

closed #848

* chore: fix typo

* chore: fix typo

* chore: update snapshot

* chore: fix typo

---------

Co-authored-by: wū yāng <[email protected]>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
  • Loading branch information
3 people authored Nov 5, 2024
1 parent bfa36a2 commit 62e4718
Show file tree
Hide file tree
Showing 9 changed files with 171 additions and 1 deletion.
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

0 comments on commit 62e4718

Please sign in to comment.