Antd的Table元件巢狀Table以及選擇框聯動操作
一、需求
在使用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',num: '5人',] },{ key: '2',title: '餐飲酒店/收銀員',number: '無門店,共5人',time: '2020.06.06 11:35',childData: [ { key: '2.1',jobTitle: '大桶大足浴',num: '0人',{ key: '2.2',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,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,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,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',] return <Table columns={childColumns} dataSource={childData} pagination={false} rowSelection={childRowSelection} /> } const onParentSelectChange = (record: 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,changeRows: any) => { let patentArr: any = [...parentSelectedRowKeys]; let setChildArr: any = []; changeRows.forEach((e: any) => { setChildArr = [...setChildArr,...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,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,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,} return ( <div> <Table columns={parentColumns} dataSource={dataSource} expandable={{ expandedRowRender }} rowSelection={parentRowSelection} /> </div> ); }
以上這篇Antd的Table元件巢狀Table以及選擇框聯動操作就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援我們。