Skip to content

Commit 0de27a5

Browse files
authored
fix(Select): fix checkall behavior when using filter props (Tencent#5104)
* fix(Select): fix checkall behavior when using filter props * chore: optimize * chore: update snapshot * chore: optimize
1 parent 012d205 commit 0de27a5

File tree

5 files changed

+39
-18
lines changed

5 files changed

+39
-18
lines changed

packages/components/select/_example/multiple.vue

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
:options="options1"
77
placeholder="请选择云解决方案"
88
multiple
9+
filterable
910
@focus="onFocus"
1011
@blur="onBlur"
1112
/>

packages/components/select/hooks/useSelectOptions.ts

+14-8
Original file line numberDiff line numberDiff line change
@@ -104,18 +104,20 @@ export const useSelectOptions = (props: TdSelectProps, keys: Ref<KeysType>, inpu
104104
return res;
105105
});
106106

107+
const filterMethods = (option: SelectOption) => {
108+
if (!props.filterable) return true;
109+
if (isFunction(props.filter)) {
110+
return props.filter(`${inputValue.value}`, option);
111+
}
112+
return option.label?.toLowerCase?.().indexOf(`${inputValue.value}`.toLowerCase()) > -1;
113+
};
114+
107115
const displayOptions = computed(() => {
108116
if (props.onSearch && props.filterable) return options.value; // 远程搜索时,不执行内部的过滤,不干预用户的自行处理,如输入首字母搜索中文的场景等
109117

110118
if (!inputValue.value || !(props.filterable || isFunction(props.filter))) return options.value;
111119

112-
const filterMethods = (option: SelectOption) => {
113-
if (isFunction(props.filter)) {
114-
return props.filter(`${inputValue.value}`, option);
115-
}
116-
117-
return option.label?.toLowerCase?.().indexOf(`${inputValue.value}`.toLowerCase()) > -1;
118-
};
120+
let checkAllOption: SelectOption;
119121

120122
let res: SelectOption[] = [];
121123

@@ -126,6 +128,9 @@ export const useSelectOptions = (props: TdSelectProps, keys: Ref<KeysType>, inpu
126128
children: (option as SelectOptionGroup).children.filter(filterMethods),
127129
});
128130
}
131+
132+
if ((option as TdOptionProps)?.checkAll === true) checkAllOption = option;
133+
129134
if (filterMethods(option)) {
130135
res.push(option);
131136
}
@@ -140,7 +145,7 @@ export const useSelectOptions = (props: TdSelectProps, keys: Ref<KeysType>, inpu
140145
res = exactMatch.concat(fuzzyMatch);
141146
}
142147

143-
return res;
148+
return res.length && checkAllOption ? [checkAllOption, ...res] : res;
144149
});
145150

146151
return {
@@ -149,5 +154,6 @@ export const useSelectOptions = (props: TdSelectProps, keys: Ref<KeysType>, inpu
149154
optionsList,
150155
optionsCache,
151156
displayOptions,
157+
filterMethods,
152158
};
153159
};

packages/components/select/select.tsx

+20-5
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,11 @@ export default defineComponent({
5959
value: props.keys?.value || 'value',
6060
disabled: props.keys?.disabled || 'disabled',
6161
}));
62-
const { optionsMap, optionsList, optionsCache, displayOptions } = useSelectOptions(props, keys, innerInputValue);
62+
const { optionsMap, optionsList, optionsCache, displayOptions, filterMethods } = useSelectOptions(
63+
props,
64+
keys,
65+
innerInputValue,
66+
);
6367

6468
// 内部数据,格式化过的
6569
const innerValue = computed(() => {
@@ -194,12 +198,17 @@ export default defineComponent({
194198

195199
/**
196200
* 可选选项的列表
197-
* 排除已禁用和全选的选项
201+
* 排除已禁用和全选的选项,考虑过滤情况
198202
*/
199203
const optionalList = computed(() =>
200204
optionsList.value.filter((item) => {
201-
// @ts-ignore types only declare checkAll not declare check-all
202-
return !item.disabled && !item['check-all'] && !item.checkAll;
205+
return (
206+
!item.disabled &&
207+
// @ts-ignore types only declare checkAll not declare check-all
208+
!item['check-all'] &&
209+
!item.checkAll &&
210+
filterMethods(item)
211+
);
203212
}),
204213
);
205214

@@ -232,14 +241,20 @@ export default defineComponent({
232241
* 根据 checked 的值计算最终选中的值:
233242
* - 如果 checked 为 true,则选中所有非 disabled 选项,并保留已选中的 disabled 选项。
234243
* - 如果 checked 为 false,则只保留已选中的 disabled 选项。
244+
* - 过滤条件下,如果 checked 为 true,则选中所有非 disabled 选项,并保留已选中的选项。
245+
* - 过滤条件下,如果 checked 为 false,则只保留已选中的 disabled 选项。
235246
*/
236247
const onCheckAllChange = (checked: boolean) => {
237248
if (!props.multiple) return;
249+
// disabled状态的选项,不参与全选的计算,始终保留
238250
const lockedValues = innerValue.value.filter((value: string | number | boolean) => {
239251
return optionsList.value.find((item) => item.value === value && item.disabled);
240252
});
253+
241254
const activeValues = optionalList.value.map((option) => option.value);
242-
const values = checked ? [...new Set([...activeValues, ...lockedValues])] : [...lockedValues];
255+
const values = checked
256+
? [...new Set([...(orgValue.value as Array<SelectValue>), ...activeValues, ...lockedValues])]
257+
: [...lockedValues];
243258
setInnerValue(values, { selectedOptions: getSelectedOptions(values), trigger: checked ? 'check' : 'clear' });
244259
};
245260

packages/tdesign-vue-next/test/unit/snap/__snapshots__/csr.test.js.snap

+3-4
Original file line numberDiff line numberDiff line change
@@ -111362,7 +111362,7 @@ exports[`csr snapshot test > csr test ./packages/components/select/_example/mult
111362111362
class="t-input__wrap t-tag-input t-tag-input--break-line t-tag-input--with-tag t-tag-input__with-suffix-icon"
111363111363
>
111364111364
<div
111365-
class="t-input t-is-readonly t-input--prefix t-input--suffix"
111365+
class="t-input t-input--prefix t-input--suffix"
111366111366
>
111367111367
<!---->
111368111368
<div
@@ -111416,12 +111416,11 @@ exports[`csr snapshot test > csr test ./packages/components/select/_example/mult
111416111416

111417111417
</div>
111418111418
<input
111419-
class="t-input__inner t-input--soft-hidden"
111419+
class="t-input__inner"
111420111420
placeholder=""
111421-
readonly=""
111422111421
spellcheck="false"
111423111422
type="text"
111424-
unselectable="on"
111423+
unselectable="off"
111425111424
/>
111426111425
<span
111427111426
class="t-input__input-pre"

0 commit comments

Comments
 (0)