Skip to content

Commit

Permalink
fix(form): select use options
Browse files Browse the repository at this point in the history
  • Loading branch information
chenshuai2144 committed Jul 17, 2023
1 parent ccc35f5 commit 59d5e72
Show file tree
Hide file tree
Showing 8 changed files with 191 additions and 144 deletions.
92 changes: 53 additions & 39 deletions packages/field/src/components/Select/SearchSelect/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { RequestOptionsType } from '@ant-design/pro-utils';
import type { SelectProps } from 'antd';
import { ConfigProvider, Select } from 'antd';

import type { LabeledValue } from 'antd/lib/select';
import type { DefaultOptionType, LabeledValue } from 'antd/lib/select';
import classNames from 'classnames';
import React, {
useContext,
Expand All @@ -12,8 +12,6 @@ import React, {
useState,
} from 'react';

const { Option, OptGroup } = Select;

// 支持 key, value, label,兼容 UserSearch 中只填写了 key 的情况。
export type KeyLabel = Partial<LabeledValue> & RequestOptionsType;

Expand Down Expand Up @@ -168,39 +166,39 @@ const SearchSelect = <T,>(props: SearchSelectProps<T[]>, ref: any) => {
return [];
};

const renderOptions = (mapOptions: RequestOptionsType[]) => {
return mapOptions.map((item) => {
const genOptions = (
mapOptions: RequestOptionsType[],
): DefaultOptionType[] => {
return mapOptions.map((item, index) => {
const {
disabled: itemDisable,
className: itemClassName,
optionType,
...resetItem
} = item as RequestOptionsType;

const label = item[labelPropsName];
const value = item[valuePropsName];
const itemOptions = item[optionsPropsName] ?? [];

if (optionType === 'optGroup' || item.options) {
return (
<OptGroup key={value} label={label}>
{renderOptions(itemOptions)}
</OptGroup>
);
return {
...resetItem,
label: label,
title: label,
key: value ?? label?.toString(),
children: genOptions(itemOptions),
} as DefaultOptionType;
}

return (
<Option
{...item}
value={value!}
key={value || label?.toString()}
disabled={itemDisable}
data-item={item}
className={`${prefixCls}-option ${itemClassName || ''}`}
label={label}
>
{optionItemRender?.(item as any) || label}
</Option>
);
return {
...resetItem,
title: label,
value: value ?? index,
key: value ?? label?.toString(),
'data-item': item,
className: `${prefixCls}-option ${itemClassName || ''}`.trim(),
label: optionItemRender?.(item as any) || label,
} as DefaultOptionType;
});
};
return (
Expand All @@ -215,18 +213,6 @@ const SearchSelect = <T,>(props: SearchSelectProps<T[]>, ref: any) => {
searchValue={searchValue}
optionFilterProp={optionFilterProp}
optionLabelProp={optionLabelProp}
filterOption={(inputValue, option) => {
return !!(
option?.label
?.toString()
.toLowerCase()
.includes(inputValue.toLowerCase()) ||
option?.value
?.toString()
.toLowerCase()
.includes(inputValue.toLowerCase())
);
}} // 这里使用pro-components的过滤逻辑
onClear={() => {
onClear?.();
fetchData(undefined);
Expand All @@ -235,6 +221,35 @@ const SearchSelect = <T,>(props: SearchSelectProps<T[]>, ref: any) => {
}
}}
{...restProps}
filterOption={
restProps.filterOption == false
? false
: (inputValue, option) => {
if (
restProps.filterOption &&
typeof restProps.filterOption === 'function'
) {
return restProps.filterOption(inputValue, {
...option,
label: option?.title,
});
}
return !!(
option?.title
?.toString()
.toLowerCase()
.includes(inputValue.toLowerCase()) ||
option?.label
?.toString()
.toLowerCase()
.includes(inputValue.toLowerCase()) ||
option?.value
?.toString()
.toLowerCase()
.includes(inputValue.toLowerCase())
);
}
} // 这里使用pro-components的过滤逻辑
onSearch={
showSearch
? (value) => {
Expand Down Expand Up @@ -283,9 +298,8 @@ const SearchSelect = <T,>(props: SearchSelectProps<T[]>, ref: any) => {
}
onFocus?.(e);
}}
>
{renderOptions(options || [])}
</Select>
options={genOptions(options || [])}
/>
);
};

Expand Down
24 changes: 17 additions & 7 deletions packages/list/src/Item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -207,22 +207,32 @@ function ProListItem<RecordType>(props: ItemProps<RecordType>) {
return [
<div
key="action"
className={`${className}-actions ${hashId}`.trim()}
className={`${defaultClassName}-actions ${hashId}`.trim()}
onClick={(e) => e.stopPropagation()}
>
{actions}
</div>,
];
}, [actions, cardActionProps, className, hashId]);
}, [actions, cardActionProps, defaultClassName, hashId]);

const titleDom =
title || subTitle ? (
<div className={`${className}-header-title ${hashId}`.trim()}>
<div className={`${defaultClassName}-header-container ${hashId}`.trim()}>
{title && (
<div className={`${className}-title ${hashId}`.trim()}>{title}</div>
<div
className={classNames(`${defaultClassName}-title`, hashId, {
[`${defaultClassName}-title-editable`]: isEditable,
})}
>
{title}
</div>
)}
{subTitle && (
<div className={`${className}-subTitle ${hashId}`.trim()}>
<div
className={classNames(`${defaultClassName}-subTitle`, hashId, {
[`${defaultClassName}-subTitle-editable`]: isEditable,
})}
>
{subTitle}
</div>
)}
Expand All @@ -248,8 +258,8 @@ function ProListItem<RecordType>(props: ItemProps<RecordType>) {
) : null;

const rowClassName = classNames(hashId, {
[`${className}-item-has-checkbox`]: checkbox,
[`${className}-item-has-avatar`]: avatar,
[`${defaultClassName}-item-has-checkbox`]: checkbox,
[`${defaultClassName}-item-has-avatar`]: avatar,
[className]: className,
});
const cardTitleDom = useMemo(() => {
Expand Down
34 changes: 21 additions & 13 deletions packages/list/src/demos/ToolBar.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { ActionType } from '@ant-design/pro-components';
import { ProList } from '@ant-design/pro-components';
import { Badge, Button } from 'antd';
import React, { useState } from 'react';
import React, { useRef, useState } from 'react';

const dataSource = [
{
Expand Down Expand Up @@ -78,13 +79,27 @@ const renderBadge = (count: number, active = false) => {

export default () => {
const [activeKey, setActiveKey] = useState<React.Key | undefined>('tab1');
const action = useRef<ActionType>();
return (
<ProList<any>
rowKey="name"
actionRef={action}
dataSource={dataSource}
editable={{}}
metas={{
title: {
dataIndex: 'name',
valueType: 'select',
fieldProps: {
showSearch: true,
placement: 'bottomRight',
options: [
{
label: '实验名称1',
value: '实验名称1',
},
],
},
},
description: {
dataIndex: 'desc',
Expand Down Expand Up @@ -126,23 +141,16 @@ export default () => {
target="_blank"
rel="noopener noreferrer"
key="link"
onClick={() => {
action.current?.startEditable(row.name);
}}
>
编辑
</a>,
<a
href={row.html_url}
target="_blank"
rel="noopener noreferrer"
key="warning"
>
<a target="_blank" rel="noopener noreferrer" key="warning">
复制
</a>,
<a
href={row.html_url}
target="_blank"
rel="noopener noreferrer"
key="view"
>
<a target="_blank" rel="noopener noreferrer" key="view">
删除
</a>,
],
Expand Down
15 changes: 13 additions & 2 deletions packages/list/src/style/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ const genProListStyle: GenerateStyle<ProListToken> = (token) => {
'&-avatar,&-description,&-title': {
paddingBlock: 6,
paddingInline: 0,
'&-editable': {
paddingBlock: 0,
},
},
},
'&-action': {
Expand Down Expand Up @@ -151,6 +154,9 @@ const genProListStyle: GenerateStyle<ProListToken> = (token) => {
marginInlineEnd: '16px',
wordBreak: 'break-all',
cursor: 'pointer',
'&-editable': {
paddingBlock: 8,
},
'&:hover': {
color: token.colorPrimary,
},
Expand All @@ -163,7 +169,12 @@ const genProListStyle: GenerateStyle<ProListToken> = (token) => {
marginBlock: 0,
marginInline: 32,
},
'&-subTitle': { color: 'rgba(0, 0, 0, 0.45)' },
'&-subTitle': {
color: 'rgba(0, 0, 0, 0.45)',
'&-editable': {
paddingBlock: 8,
},
},
'&-description': { marginBlockStart: '4px', wordBreak: 'break-all' },
'&-avatar': { display: 'flex' },
'&-header': {
Expand All @@ -175,7 +186,7 @@ const genProListStyle: GenerateStyle<ProListToken> = (token) => {
padding: 0,
},
},
'&-header-title': {
'&-header-container': {
display: 'flex',
alignItems: 'center',
justifyContent: 'flex-start',
Expand Down
7 changes: 4 additions & 3 deletions packages/utils/src/useEditableArray/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,8 @@ export function SaveEditableAction<T>(
});

const fields =
context.getFieldFormatValue?.(namePath) || form.getFieldValue(namePath);
context?.getFieldFormatValue?.(namePath) ||
form.getFieldValue(namePath);
// 处理 dataIndex 为数组的情况
if (Array.isArray(recordKey) && recordKey.length > 1) {
// 获取 namepath
Expand Down Expand Up @@ -481,8 +482,8 @@ const CancelEditableAction: React.FC<ActionRenderConfig<any> & { row: any }> = (
.flat(1)
.filter(Boolean) as string[];
const fields =
context.getFieldFormatValue?.(namePath) ||
form.getFieldValue(namePath);
context?.getFieldFormatValue?.(namePath) ||
form?.getFieldValue(namePath);
const record = isMapEditor ? set({}, namePath, fields) : fields;
const res = await onCancel?.(recordKey, record, row, newLineConfig);
await cancelEditable(recordKey);
Expand Down
15 changes: 9 additions & 6 deletions tests/form/base.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2719,12 +2719,15 @@ describe('ProForm', () => {
);
});

// 应该有4个item 被筛选出来
expect(
wrapper.baseElement.querySelectorAll<HTMLElement>(
'div.ant-select-item.ant-select-item-option',
).length,
).toBe(4);
await waitFor(() => {
// 应该有4个item 被筛选出来
expect(
wrapper.baseElement.querySelectorAll<HTMLElement>(
'div.ant-select-item.ant-select-item-option',
).length,
).toBe(4);
});

// input 也有输入的内容
expect(
wrapper.baseElement.querySelectorAll<HTMLInputElement>(
Expand Down
Loading

0 comments on commit 59d5e72

Please sign in to comment.