Antd的Table组件嵌套Table以及选择框联动操作
作者:MinorF_γ
一、需求
在使用Table组件嵌套Table时,父子Table的选择框需要联动,即父Table选中,该行下的子Table需要全选中,某一个子Table全部选中,则该子Table所在的父Table那一行也需要选中。
二、Table的rowSelection配置
父子Table联动,就不能使用OnChange,需要使用OnSelect以及OnSelectAll手动配置。
selectedRowKeys:指定选中项的key数组
OnSelect:手动选择/取消选择某行的回调
OnSelect(record, selected, selectedRows)
record:选中的当前行数据
selected:选中状态,true:选中,false:取消选中
selectedRows:选择的数组
OnSelectAll:手动选择/取消选择所有行的回调
OnSelect(selected, selectedRows, changeRows)
selected:选中状态,true:选中,false:取消选中
selectedRows:选择的数组
changeRows:改变的所有数组
三、根据antd文档搭建Table嵌套Table界面
import React, { useEffect, useState } from 'react'; import { Table, } from 'antd' export default () => { const dataSource: any = [ { key: '1', title: '餐饮酒店/服务员', number: '8家门店,共8人', time: '2020.05.25 15:35', childData: [ { key: '1.1', jobTitle: '大桶大足浴-保安', num: '2人', }, { key: '1.2', jobTitle: '大桶大足浴-保安', num: '5人', }, ] }, { key: '2', title: '餐饮酒店/收银员', number: '无门店,共5人', time: '2020.06.06 11:35', childData: [ { key: '2.1', jobTitle: '大桶大足浴', num: '0人', }, { key: '2.2', jobTitle: '大桶大足浴', num: '1人', }, ] }, ] const parentColumns: any = [ { title: '工种', dataIndex: 'title', key: 'title', }, { title: '关联门店数', dataIndex: 'number', key: 'number', }, { title: '时间', dataIndex: 'time', key: 'time', }, ] const expandedRowRender = (record: any, index: any, indent: any, expanded: any) => { const childData = record.childData const childColumns: any = [ { title: '岗位名称', dataIndex: 'jobTitle', key: 'jobTitle' }, { title: '招聘人数', dataIndex: 'num', key: 'num' }, ] return <Table columns={childColumns} dataSource={childData} pagination={false} rowSelection={childRowSelection} /> } return ( <div> <Table columns={parentColumns} dataSource={dataSource} expandable={{ expandedRowRender }} rowSelection={parentRowSelection} /> </div> ); }
四、开始配置rowSelection
1、配置父子Table的rowSelection
const childRowSelection = { selectedRowKeys: childSelectedRowKeys, onSelect: onChildSelectChange, onSelectAll: onChildSelectAll } const parentRowSelection = { selectedRowKeys: parentSelectedRowKeys, onSelect: onParentSelectChange, onSelectAll: onParentSelectAll, }
2、创建childSelectedRowKeys,parentSelectedRowKeys变量,用来存放父子Table选中的key值
const [parentSelectedRowKeys, setParentSelectedRowKeys] = useState<any>([])
const [childSelectedRowKeys, setChildSelectedRowKeys] = useState<any>([])
3、设置子Table手动选择/取消某行的回调 onChildSelectChange
选择单个时,当前行选中,若将该Table的所有选项全部选中,则子Table对应的父Table所在的那一行也选中
const onChildSelectChange = (record: any, selected: any, selectedRows: any) => { let childArr: any = [...childSelectedRowKeys]; //第一步 判断selected true:选中,将key值添加到childArr,false:取消选中,将key值从childArr中移除 if (selected) { childArr.push(record.key) } else { childArr.splice(childArr.findIndex((item: any) => item === record.key), 1) } //必须去除undefined,否则selectedRows会将其他子Table中选中的key值放到数组中,但是值为undefined,如:[ undefined,1,uundefined] selectedRows = selectedRows.filter((a: any) => a !== undefined) //第二步,判断selectedRows的长度是否为data中child的长度,相等,就将父table选中,不等就不选中 for (let item of dataSource) { if (item.childData.find((d: any) => d.key === record.key)) { let parentArr: any = [...parentSelectedRowKeys]; if (item.childData.length === selectedRows.length) { parentArr.push(item.key) } else { if (parentArr.length && parentArr.find((d: any) => d === item.key)) { parentArr.splice(parentArr.findIndex((item1: any) => item1 === item.key), 1) } } setParentSelectedRowKeys(parentArr) break; } } setChildSelectedRowKeys(childArr) }
4、设置子Table手动选择/取消选择所有行的回调onChildSelectAll
当选择全选时,子Table全部选中,并且该子table对应的父table行也选中,取消全选时,子Table全部取消选中,父Table行也取消选中
const onChildSelectAll = (selected: any, selectedRows: any, changeRows: any) => { //第一步:判断selected,true:将子Table全部选中,false:将子Table全部取消选中 let childArr: any = [...childSelectedRowKeys]; if (selected) { //全选 childArr = Array.from(new Set([...childArr, ...changeRows.map((item: any) => item.key)])) } else { //取消全选 childArr = childArr.filter((item: any) => !changeRows.some((e: any) => e.key === item)) } //第二步:找到子Table对应的父Table的所在行,再判断selected,true:将父Table所在行选中,false:将父Table所在行取消选中 for (let item of dataSource) { if (item.childData.find((d: any) => d.key === changeRows[0].key)) { let parentArr: any = [...parentSelectedRowKeys]; if (selected) { //全选 parentArr.push(item.key) } else { //取消全选 parentArr.splice(parentArr.findIndex((item: any) => item === item.key), 1) } setParentSelectedRowKeys(parentArr) break; } } setChildSelectedRowKeys(childArr) }
5、设置父Table手动选择/取消某行的回调 onParentSelctChange
当选择父Table某一行时,该行下的子Table全部选中,取消选择时,该行下的子Table也全部取消选中
const onParentSelectChange = (record: any, selected: any, selectedRows: any) => { let patentArr: any = [...parentSelectedRowKeys]; let childArr: any = [...childSelectedRowKeys]; //setChildArr:选择父Table下的所有子选项 let setChildArr = dataSource.find((d: any) => d.key === record.key).childData.map((item: any) => item.key) //第一步 判断selected true:选中,false,取消选中 if (selected) { //第二步,父Table选中,子Table全选中(全部整合到一起,然后去重) patentArr.push(record.key) childArr = Array.from(new Set([...setChildArr, ...childArr])) } else { //第二步,父Table取消选中,子Table全取消选中(针对childArr,过滤掉取消选中的父Table下的所有子Table的key) patentArr.splice(patentArr.findIndex((item: any) => item === record.key), 1) childArr = childArr.filter((item: any) => !setChildArr.some((e: any) => e === item)) } //第三步,设置父,子的SelectedRowKeys setParentSelectedRowKeys(patentArr) setChildSelectedRowKeys(childArr) }
6、设置父Table手动选择/取消选择所有行的回调onParentSelectAll
全选时,父Table全部选中,所有对应的子Table也全部选中。取消全选时,父Table取消选中,所有子Table也取消选中
const onParentSelectAll = (selected: any, selectedRows: any, changeRows: any) => { let patentArr: any = [...parentSelectedRowKeys]; let setChildArr: any = []; //将改变的父Table下的子Table下的key都添加到setChildArr中 changeRows.forEach((e: any) => { setChildArr = [...setChildArr, ...e.childData.map((item: any) => item.key)] }); //第一步判断selected true:全选,false:取消全选 if (selected) { //第二步:父Table选中,子Table全选中,设置子Table的SelectedRowKeys patentArr = Array.from(new Set([...patentArr, ...changeRows.map((item: any) => item.key)])) setChildSelectedRowKeys(setChildArr) } else { //第二步:父Table取消选中,子Table全取消选中,设置子Table的SelectedRowKeys patentArr = patentArr.filter((item: any) => !changeRows.some((e: any) => e.key === item)) setChildSelectedRowKeys([]) } //第三步:设置父Table的SelectedRowKeys setParentSelectedRowKeys(patentArr) }
这样,父子Table的选择框联动就完成了,
注意:dataSource数据格式根据自己的格式而定
五、完整Demo
Table嵌套Table完整代码
import React, { useEffect, useState } from 'react'; import { Table, Button } from 'antd' import { PlusOutlined } from '@ant-design/icons'; export default () => { const [parentSelectedRowKeys, setParentSelectedRowKeys] = useState<any>([]) const [childSelectedRowKeys, setChildSelectedRowKeys] = useState<any>([]) console.log(parentSelectedRowKeys, 'parentSelectedRowKeys') console.log(childSelectedRowKeys, 'childSelectedRowKeys') const dataSource: any = [ { key: '1', title: '餐饮酒店/服务员', number: '8家门店,共8人', time: '2020.05.25 15:35', childData: [ { key: '1.1', jobTitle: '大桶大足浴-保安', num: '2人', }, { key: '1.2', jobTitle: '大桶大足浴-保安', num: '5人', }, ] }, { key: '2', title: '餐饮酒店/收银员', number: '无门店,共5人', time: '2020.06.06 11:35', childData: [ { key: '2.1', jobTitle: '大桶大足浴', num: '0人', }, { key: '2.2', jobTitle: '大桶大足浴', num: '1人', }, ] }, ] const parentColumns: any = [ { title: '工种', dataIndex: 'title', key: 'title', }, { title: '关联门店数', dataIndex: 'number', key: 'number', }, { title: '时间', dataIndex: 'time', key: 'time', }, ] const expandedRowRender = (record: any, index: any, indent: any, expanded: any) => { const childData = record.childData const childColumns: any = [ { title: '岗位名称', dataIndex: 'jobTitle', key: 'jobTitle' }, { title: '招聘人数', dataIndex: 'num', key: 'num' }, ] return <Table columns={childColumns} dataSource={childData} pagination={false} rowSelection={childRowSelection} /> } const onParentSelectChange = (record: any, selected: any, selectedRows: any) => { let patentArr: any = [...parentSelectedRowKeys]; let childArr: any = [...childSelectedRowKeys]; //setChildArr:选择父Table下的所有子选项 let setChildArr = dataSource.find((d: any) => d.key === record.key).childData.map((item: any) => item.key) //第一步 判断selected true:选中,false,取消选中 if (selected) { //第二步,父Table选中,子Table全选中 patentArr.push(record.key) childArr = Array.from(new Set([...setChildArr, ...childArr])) } else { //第二步,父Table取消选中,子Table全取消选中 patentArr.splice(patentArr.findIndex((item: any) => item === record.key), 1) childArr = childArr.filter((item: any) => !setChildArr.some((e: any) => e === item)) } //第三步,设置父,子的SelectedRowKeys setParentSelectedRowKeys(patentArr) setChildSelectedRowKeys(childArr) } const onParentSelectAll = (selected: any, selectedRows: any, changeRows: any) => { let patentArr: any = [...parentSelectedRowKeys]; let setChildArr: any = []; changeRows.forEach((e: any) => { setChildArr = [...setChildArr, ...e.childData.map((item: any) => item.key)] }); //第一步判断selected true:全选,false:取消全选 if (selected) { //第二步:父Table选中,子Table全选中,设置子Table的SelectedRowKeys patentArr = Array.from(new Set([...patentArr, ...changeRows.map((item: any) => item.key)])) setChildSelectedRowKeys(setChildArr) } else { //第二步:父Table取消选中,子Table全取消选中,设置子Table的SelectedRowKeys patentArr = patentArr.filter((item: any) => !changeRows.some((e: any) => e.key === item)) setChildSelectedRowKeys([]) } //第三步:设置父Table的SelectedRowKeys setParentSelectedRowKeys(patentArr) } const onChildSelectChange = (record: any, selected: any, selectedRows: any) => { //record:当前操作行 //selected选中状态 //selectedRows:选择的数组 let childArr: any = [...childSelectedRowKeys]; //第一步 判断selected true:选中,false:取消选中 if (selected) { childArr.push(record.key) } else { childArr.splice(childArr.findIndex((item: any) => item === record.key), 1) } selectedRows = selectedRows.filter((a: any) => a !== undefined) //第二步,判断selectedRows的长度是否为data中child的长度,相等,就将父table选中,不等就不选中 for (let item of dataSource) { if (item.childData.find((d: any) => d.key === record.key)) { let parentArr: any = [...parentSelectedRowKeys]; if (item.childData.length === selectedRows.length) { parentArr.push(item.key) } else { if (parentArr.length && parentArr.find((d: any) => d === item.key)) { parentArr.splice(parentArr.findIndex((item1: any) => item1 === item.key), 1) } } setParentSelectedRowKeys(parentArr) break; } } setChildSelectedRowKeys(childArr) } const onChildSelectAll = (selected: any, selectedRows: any, changeRows: any) => { //selected:全选true 取消全选false //selectedRows:改变后的 //changeRows:改变的所有数组 //第一步:判断selected,true:将子Table全部选中,false:将子Table全部取消选中 let childArr: any = [...childSelectedRowKeys]; if (selected) { //全选 childArr = Array.from(new Set([...childArr, ...changeRows.map((item: any) => item.key)])) } else { //取消全选 childArr = childArr.filter((item: any) => !changeRows.some((e: any) => e.key === item)) } //第二步:找到子Table对应的父Table的所在行,再判断selected,true:将父Table所在行选中,false:将父Table所在行取消选中 for (let item of dataSource) { if (item.childData.find((d: any) => d.key === changeRows[0].key)) { let parentArr: any = [...parentSelectedRowKeys]; if (selected) { //全选 parentArr.push(item.key) } else { //取消全选 parentArr.splice(parentArr.findIndex((item: any) => item === item.key), 1) } setParentSelectedRowKeys(parentArr) break; } } setChildSelectedRowKeys(childArr) } const childRowSelection = { selectedRowKeys: childSelectedRowKeys, onSelect: onChildSelectChange, onSelectAll: onChildSelectAll } const parentRowSelection = { selectedRowKeys: parentSelectedRowKeys, onSelect: onParentSelectChange, onSelectAll: onParentSelectAll, } return ( <div> <Table columns={parentColumns} dataSource={dataSource} expandable={{ expandedRowRender }} rowSelection={parentRowSelection} /> </div> ); }
以上这篇Antd的Table组件嵌套Table以及选择框联动操作就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持脚本之家。