mirror of
https://gitee.com/nocobase/nocobase.git
synced 2024-12-01 11:47:51 +08:00
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:
parent
9684e55f1a
commit
a648adace8
@ -16,4 +16,5 @@ export * from './page';
|
||||
export * from './password';
|
||||
export * from './radio';
|
||||
export * from './time-picker';
|
||||
export * from './tree-select';
|
||||
export * from './upload';
|
||||
|
@ -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>
|
||||
);
|
||||
});
|
@ -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;
|
@ -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>
|
||||
);
|
||||
};
|
@ -6,3 +6,9 @@ group:
|
||||
---
|
||||
|
||||
# TreeSelect
|
||||
|
||||
## Examples
|
||||
|
||||
### TreeSelect
|
||||
|
||||
<code src="./demos/demo1.tsx" />
|
||||
|
@ -0,0 +1 @@
|
||||
export * from './TreeSelect';
|
Loading…
Reference in New Issue
Block a user