Appearance
antd 树形 table 实现父子联动选择
antd table 文档 暂不支持父子数据递归关联选择。
antd 的 tree table 未实现父子关联选择,需要自行实现

想要的效果如下

tsx
// 获取所有后代
const getOffspringKeys = (list: any[]) => {
const ret: any[] = []
list.forEach((item) => {
ret.push(item.key)
if (item.children && item.children.length) {
ret.push(...getOffspringKeys(item.children))
}
})
return ret
}
// 处理 tree 数据: 裁剪字段 + 父子关联数据,_parent _offspringKeys
const formatData = (list: any[], parent: any[] = []): any[] =>
list.map((item) => {
const base = _.pick(item, ['key', 'name'])
if (item.children && item.children.length) {
const keys = item.children.map((x: any) => x.key)
const children = formatData(item.children, [...parent, { key: item.key, children: keys }])
const _offspringKeys = getOffspringKeys(item.children)
return { ...base, children, _offspringKeys, _parent: parent }
}
return { ...base, _parent: parent }
})tsx
const [selectedKeys, setSelectedKeys] = useState<any[]>([])
// 单选 / 多选
const rowSelection: TableRowSelection<any> = {
type: 'checkbox',
selectedRowKeys: selectedKeys,
getCheckboxProps: (record: any) => {
let indeterminate = false // 半选
if (record._offspringKeys) {
const inter = _.intersection(selectedKeys, record._offspringKeys)
indeterminate = inter.length > 0 && inter.length < record._offspringKeys.length
}
return { indeterminate }
},
onSelect: (record: any, selected: any) => {
let retKeys: any[] = []
const children = record._offspringKeys || []
if (selected) {
retKeys = _.union(selectedKeys, [record.key], children) // 选中自己 + 后代
// 选中上游节点
_.forEachRight(record._parent, (el) => {
const hasNot = el.children.some((x: any) => retKeys.indexOf(x) === -1)
if (!hasNot) {
retKeys.push(el.key)
}
})
} else {
retKeys = _.without(selectedKeys, record.key, ...children) // 取消自己 + 后代
// 取消上游节点
_.forEachRight(record._parent, (el) => {
const hasNot = el.children.some((x: any) => retKeys.indexOf(x) === -1)
if (hasNot) {
retKeys = retKeys.filter((x) => x !== el.key)
}
})
}
setSelectedKeys(retKeys)
},
}tsx
const tableDataDemo = [
{
key: 1,
name: 'John Brown sr.',
age: 60,
address: 'New York No. 1 Lake Park',
children: [
{
key: 13,
name: 'Jim Green sr.',
age: 72,
address: 'London No. 1 Lake Park',
children: [
{
key: 131,
name: 'Jim Green',
age: 42,
address: 'London No. 2 Lake Park',
children: [
{
key: 1311,
name: 'Jim Green jr.',
age: 25,
address: 'London No. 3 Lake Park',
},
{
key: 1312,
name: 'Jimmy Green sr.',
age: 18,
address: 'London No. 4 Lake Park',
},
],
},
],
},
{
key: 11,
name: 'John Brown',
age: 42,
address: 'New York No. 2 Lake Park',
},
],
},
]
const tableData = formatData(tableDataDemo)
<Table
rowKey="key"
columns={columns}
showHeader={false}
pagination={false}
rowSelection={rowSelection}
dataSource={tableData}
/>