该组件的功能有:
1.可设置搜索功能
2.可以每级可选,也可以选择只能最后一级里面的选项可选
3.当组件是只能最后一级里面的选项可选时, 点击文字展开下级选项
- import React, { ReactNode, useEffect, useState } from 'react';
- import { Form, TreeSelect } from 'antd';
- import _, { get, isEmpty } from 'lodash';
- import styles from './SimpleTreeSelect.module.css';
- import { arrayLengthMoreThanZero } from 'utils/formatHelper';
- import './SimpleTreeSelect.css';
-
- interface ITreeSelectProps {
- label: string;
- name: any;
- required?: boolean;
- errorMessage?: string;
- placeHolder?: string;
- optionValue?: string;
- optionLabel?: string;
- value?: string;
- width?: string;
- addAll?: boolean;
- allOption?: object;
- labelStyle?: React.CSSProperties;
- containerStyle?: React.CSSProperties;
- disabled?: boolean;
- showSearch?: boolean;
- onChange?: (value: string, arg2?: ReactNode[], arg3?: any) => void;
- onFocus?: (arg: any) => void;
- allLabel?: string;
- allValue?: string;
- hideOptionValue?: string | string[];
- validator?: (arg1: any, arg2: any) => any;
- bottomContent?: string | JSX.Element;
- showArrowIcon?: boolean;
- option: ItreeNodeItem[];
- onLoadData?: (arg: any) => any;
- allCanSelect?: boolean;
- }
-
- interface ItreeNodeItem {
- id?: string;
- pId?: string;
- value?: string;
- title?: string;
- disabled?: boolean;
- isLeaf?: boolean;
- }
-
- export const SimpleTreeSelect = (props: ITreeSelectProps) => {
-
- const {
- label,
- name,
- required = false,
- errorMessage = '必选',
- // placeHolder = '请选择',
- value,
- option: initOption,
- width = 290,
- addAll = true,
- labelStyle,
- containerStyle,
- disabled = false,
- allOption,
- onChange,
- showSearch = true,
- allLabel = '全部',
- allValue = '',
- hideOptionValue,
- validator,
- bottomContent = '',
- showArrowIcon = true,
- onFocus,
- onLoadData,
- allCanSelect = false,
- } = props;
- const [option, setOption] = useState<any[]>(initOption);
-
- /**
- * option: select数据,为对象数组
- * 隐藏掉指定value的选项hideOptionValue
- *
- */
- useEffect(() => {
- if (allCanSelect) return;
- const option: any[] = initOption;
- for (let item of option) {
- const arr = (option || []).filter(its => get(its, ['pId']) === get(item, ['id'])) || [];
- item.disabled = arrayLengthMoreThanZero(arr);
- }
- if (addAll) {
- option.unshift({
- pId: allValue,
- value: allValue,
- title: allLabel,
- })
- }
- if (typeof hideOptionValue === 'string' && hideOptionValue) {
- const idx = _.findIndex(option, item => get(item, ['id']) === hideOptionValue);
- if (idx >= 0) option.splice(idx, 1);
- }
- if (arrayLengthMoreThanZero(hideOptionValue)) {
- const hideOption = hideOptionValue || []
- const arr: any[] = _.filter(option, item => {
- for (let its of hideOption) {
- if (get(item, ['id']) !== its) return item;
- }
- }) || [];
- setOption(arr);
- }
- else {
- setOption(option);
- }
- }, [initOption, hideOptionValue, allCanSelect]);
-
-
- const placeHolder = props.placeHolder || (disabled ? '' : '请选择');
-
- const renderLabel = () => {
- return (
- <span className={styles.label} style={labelStyle}>
- {required && <span className={styles.star}>*</span>}
- {label}
- </span>
- );
- };
-
- const renderArrowIcon = () => showArrowIcon ? <span className={styles.arrowIcon} /> : <></>;
-
- return (
- <div style={containerStyle} className={styles.selectContainer}>
- <Form.Item colon={false} label={renderLabel()}>
- <Form.Item
- name={name}
- colon={false}
- noStyle
- validateFirst
- initialValue={value}
- rules={
- validator
- ? [{ required: required, message: errorMessage }, { validator }]
- : [{ required: required, message: errorMessage }]
- }
- >
- <TreeSelect
- treeDataSimpleMode
- showSearch={showSearch}
- treeNodeFilterProp={'title'}//输入项过滤对应的 treeNode 属性, value或者title
- style={{ width: width && /^\d+$/.test(width.toString()) ? `${width}px` : width }}
- dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
- allowClear
- treeDefaultExpandAll={false}
- onChange={(value, label, extra) => {
- onChange && onChange(value, label, extra)
- }}
- onClick={e=> {
- const vvv:any = e.target||{};
- const el:any = get(vvv.parentNode.children, [1]) || get(vvv.parentNode.parentNode.children, [1]);
- try {
- if('click' in el) {
- el.click();
- }
- else {
- const evt:any = document.createEvent('Event');
- evt.initEvent('click', true, true);
- el.dispatchEvent(evt);
- }
- }
- catch(err) {
- console.log(err)
- }
- }}
- onFocus={onFocus}
- loadData={onLoadData}
- value={value}
- placeholder={placeHolder}
- treeData={option}
- disabled={disabled}
- suffixIcon={renderArrowIcon()}
- >
- </TreeSelect>
- </Form.Item>
- {!isEmpty(bottomContent) && <div style={{ margin: 0 }}>
- <div style={{ marginBottom: '-5px' }}>
- {bottomContent}
- </div>
- </div>}
- </Form.Item>
- </div>
- );
- };
treeData数据示例:
const arr0 = [
{
id: 1,
pId: 0,
value: 'leaf-1',
title: '属性图1'
},
{
id: 2,
pId: 1,
value: 'leaf-2',
title: '属性图2'
},
{
id: 3,
pId: 0,
value: 'leaf-3',
title: '属性图3'
}
];
let [treeData, setTreeData] = useState
CustomSimpleTreeSelect的简单使用:
labelStyle={labelStyle}
containerStyle={containerStyle}
addAll={false}
name="xxx"
label="xxx"
required
/>