如上大致为需求UI图以及相关操作:
大致思路:需要一个折叠控制组件,以及带有父级勾选的子组件,以及整个界面组件;
折叠控制组件:
//折叠组件
const { isShow: showIcon, changeStatus: handleToogleIcon } = useToogleStatus(true);
<ToggleIcon show={showIcon} toggleList={handleToogleIcon}></ToggleIcon>
import { useState } from 'react';
export const useToogleStatus = (intial: boolean) => {
const [isShow, setIsShow] = useState<boolean>(intial);
const changeStatus = () => {
setIsShow(!isShow);
};
return {
isShow,
changeStatus,
};
};
import styles from './index.scss';
export interface IProps {
show: boolean;
toggleList: () => void;
}
const ToggleIcon = (props: IProps) => {
return (
<>
<div className={styles['label-title']} onClick={props.toggleList}>
<div
className={
props.show ? styles['labelTitleIconShow'] : styles['labelTitleIconHide']
}></div>
</div>
</>
);
};
export default ToggleIcon;
@mixin box-common {
width: 0;
height: 0;
margin-left: 5px;
margin-top: 5px;
cursor: pointer;
border: 4px solid transparent;
}
.label-title {
font-size: 14px;
font-weight: 700;
padding: 10px 0;
margin-top: 10px;
margin-right: 5px;
cursor: pointer;
.labelTitleIconShow {
@include box-common;
border-top: 6px solid #c3cad9;
}
.labelTitleIconHide {
@include box-common;
border-left: 6px solid #c3cad9;
}
}
带有父级的勾选子组件
export interface LabelValueType {
label: string;
value: string;
}
export interface IConcernedOption {
label: string;
value: string;
isPrimaryKey: boolean;
}
export const VariableCheckbox = (props: {
form: FormInstance<any>;
checkAllName: LabelValueType;
plainOptions: IConcernedOption[];
isSearch: boolean;
curOptionsValueList: string[];
defaultCheckedList: string[];
}) => {
const { isShow: showIcon, changeStatus: handleToogleIcon } = useToogleStatus(true);
const [checkAll, setCheckAll] = useState<boolean>(false);
const [indeterminateStatus, setIndeterminateStatus] = useState<boolean | undefined>(false);
const onChange = () => {
const selectdValue = props.form.getFieldValue('concernVars');
const list = Object.keys(pickBy(selectdValue, (value) => value));
const curCheckboxSelected = list.filter((varItem) =>
props.curOptionsValueList.includes(varItem),
);
setIndeterminateStatus(
curCheckboxSelected.length > 0 && curCheckboxSelected.length < props.plainOptions.length,
);
setCheckAll(props.plainOptions.length === curCheckboxSelected.length);
};
const onCheckAllChange: CheckboxProps['onChange'] = (e) => {
const checkStatus = e.target.checked;
setCheckAll(checkStatus);
props.plainOptions.forEach((optionsItem) => {
if (!optionsItem.isPrimaryKey)
props.form.setFieldValue(['concernVars', optionsItem.value], checkStatus);
});
const checklist = checkStatus
? props.plainOptions.map((optionsItem) => optionsItem.value)
: props.plainOptions.filter((optionsItem) => optionsItem.isPrimaryKey);
setIndeterminateStatus(checklist.length > 0 && !checkStatus);
};
/** 勾选值回显 */
useEffect(() => {
if (props.defaultCheckedList.length) {
props.defaultCheckedList.forEach((keyItem: string) => {
props.form.setFieldValue(['concernVars', keyItem], true);
});
setCheckAll(props.defaultCheckedList.length === props.plainOptions.length);
setIndeterminateStatus(
props.defaultCheckedList.length > 0 &&
props.defaultCheckedList.length < props.plainOptions.length,
);
}
}, [props.defaultCheckedList]);
return (
<>
<div className={styles['title-container']}>
<ToggleIcon show={showIcon} toggleList={handleToogleIcon}></ToggleIcon>
<Checkbox
indeterminate={indeterminateStatus}
onChange={onCheckAllChange}
checked={checkAll}>
{props.checkAllName.label}
</Checkbox>
</div>
<div style={showIcon ? {} : { display: 'none' }} className={styles['option-container']}>
<div className={styles['option-container-inner']}>
{props.plainOptions.map((item) => {
return (
<Form.Item
name={['concernVars', item.value]}
noStyle
key={item.value}
valuePropName="checked">
{item.isPrimaryKey ? (
<Checkbox
key={item.value}
disabled={item.isPrimaryKey}
defaultChecked={item.isPrimaryKey}>
{item.label}
</Checkbox>
) : (
<Checkbox key={item.value} onChange={onChange}>
{item.label}
</Checkbox>
)}
</Form.Item>
);
})}
</div>
</div>
</>
);
};
具体使用
{(renderVariableOptions ?? []).map((variableItem, index) => {
return (
<VariableCheckbox
form={form}
checkAllName={variableItem.checkAllName}
plainOptions={variableItem.options}
key={index}
isSearch={isSearch}
curOptionsValueList={
datasourceVarMap.get(variableItem.checkAllName.value) as string[]
}
defaultCheckedList={
defaultCheckedObj[variableItem.checkAllName.value]
}></VariableCheckbox>
);
})}