feat: add TreeSelect component into schema components (#167)

* feat: migrate TreeSelect into schema components

* fix: modify enum to tredata

* fix: options replace treeData

* feat: migrate TreeSelect into schema components

* fix: modify enum to tredata

* fix: options replace treeData
This commit is contained in:
SemmyWong 2022-01-25 10:50:44 +08:00 committed by GitHub
parent 9684e55f1a
commit a648adace8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 172 additions and 0 deletions

View File

@ -16,4 +16,5 @@ export * from './page';
export * from './password'; export * from './password';
export * from './radio'; export * from './radio';
export * from './time-picker'; export * from './time-picker';
export * from './tree-select';
export * from './upload'; export * from './upload';

View File

@ -0,0 +1,56 @@
import { usePrefixCls } from '@formily/antd/esm/__builtins__';
import { Field } from '@formily/core';
import { observer, useField } from '@formily/react';
import { isArr } from '@formily/shared';
import { Tag } from 'antd';
import { TreeSelectProps } from 'antd/lib/tree-select';
import cls from 'classnames';
import React from 'react';
export const ReadPretty: React.FC<TreeSelectProps<any>> = observer((props) => {
const field = useField<Field>();
const { placeholder } = props;
const prefixCls = usePrefixCls('description-tree-select', props);
const dataSource = field?.dataSource?.length ? field.dataSource : props?.treeData?.length ? props.treeData : [];
const getSelected = () => {
const value = props.value;
if (props.multiple) {
if (props.labelInValue) {
return isArr(value) ? value : [];
} else {
return isArr(value) ? value.map((val) => ({ label: val, value: val })) : [];
}
} else {
if (props.labelInValue) {
return value ? [value] : [];
} else {
return value ? [{ label: value, value }] : [];
}
}
};
const findLabel = (value: any, dataSource: any[]) => {
for (let i = 0; i < dataSource?.length; i++) {
const item = dataSource[i];
if (item?.value === value) {
return item?.label;
} else {
const childLabel = findLabel(value, item?.children);
if (childLabel) return childLabel;
}
}
};
const getLabels = () => {
const selected = getSelected();
if (!selected?.length) return <Tag>{placeholder}</Tag>;
return selected.map(({ value, label }, key) => {
return <Tag key={key}>{findLabel(value, dataSource) || label || placeholder}</Tag>;
});
};
return (
<div className={cls(prefixCls, props.className)} style={props.style}>
{getLabels()}
</div>
);
});

View File

@ -0,0 +1,23 @@
import { LoadingOutlined } from '@ant-design/icons';
import { connect, mapProps, mapReadPretty } from '@formily/react';
import { TreeSelect as AntdTreeSelect } from 'antd';
import React from 'react';
import { ReadPretty } from './ReadPretty';
export const TreeSelect = connect(
AntdTreeSelect,
mapProps(
{
dataSource: 'treeData',
},
(props, field) => {
return {
...props,
suffixIcon: field?.['loading'] || field?.['validating'] ? <LoadingOutlined /> : props.suffixIcon,
};
},
),
mapReadPretty(ReadPretty),
);
export default TreeSelect;

View File

@ -0,0 +1,85 @@
/**
* title: TreeSelect
*/
import { FormItem } from '@formily/antd';
import { SchemaComponent, SchemaComponentProvider, TreeSelect } from '@nocobase/client';
import React from 'react';
const dataSource = [
{
label: '选项1',
value: 1,
children: [
{
label: 'Child Node1',
value: '0-0-0',
},
{
label: 'Child Node2',
value: '0-0-1',
},
{
label: 'Child Node3',
value: '0-0-2',
},
],
},
{
label: '选项2',
value: 2,
children: [
{
label: 'Child Node1',
value: '0-1-0',
},
{
label: 'Child Node2',
value: '0-1-1',
},
{
label: 'Child Node3',
value: '0-1-2',
},
],
},
];
const schema = {
type: 'object',
properties: {
input: {
type: 'string',
title: `Editable`,
'x-decorator': 'FormItem',
'x-component': 'TreeSelect',
'x-component-props': {
treeData: dataSource,
},
'x-reactions': {
target: 'read',
fulfill: {
state: {
value: '{{$self.value}}',
},
},
},
},
read: {
type: 'string',
title: `Read pretty`,
'x-read-pretty': true,
'x-decorator': 'FormItem',
'x-component': 'TreeSelect',
'x-component-props': {
treeData: dataSource,
},
},
},
};
export default () => {
return (
<SchemaComponentProvider components={{ TreeSelect, FormItem }}>
<SchemaComponent schema={schema} />
</SchemaComponentProvider>
);
};

View File

@ -6,3 +6,9 @@ group:
--- ---
# TreeSelect # TreeSelect
## Examples
### TreeSelect
<code src="./demos/demo1.tsx" />

View File

@ -0,0 +1 @@
export * from './TreeSelect';