Antd的Table組件嵌套Table以及選擇框聯(lián)動(dòng)操作
一、需求
在使用Table組件嵌套Table時(shí),父子Table的選擇框需要聯(lián)動(dòng),即父Table選中,該行下的子Table需要全選中,某一個(gè)子Table全部選中,則該子Table所在的父Table那一行也需要選中。
二、Table的rowSelection配置
父子Table聯(lián)動(dòng),就不能使用OnChange,需要使用OnSelect以及OnSelectAll手動(dòng)配置。
selectedRowKeys:指定選中項(xiàng)的key數(shù)組
OnSelect:手動(dòng)選擇/取消選擇某行的回調(diào)
OnSelect(record, selected, selectedRows)
record:選中的當(dāng)前行數(shù)據(jù)
selected:選中狀態(tài),true:選中,false:取消選中
selectedRows:選擇的數(shù)組
OnSelectAll:手動(dòng)選擇/取消選擇所有行的回調(diào)
OnSelect(selected, selectedRows, changeRows)
selected:選中狀態(tài),true:選中,false:取消選中
selectedRows:選擇的數(shù)組
changeRows:改變的所有數(shù)組
三、根據(jù)antd文檔搭建Table嵌套Table界面
import React, { useEffect, useState } from 'react';
import { Table, } from 'antd'
export default () => {
const dataSource: any = [
{
key: '1',
title: '餐飲酒店/服務(wù)員',
number: '8家門(mén)店,共8人',
time: '2020.05.25 15:35',
childData: [
{
key: '1.1',
jobTitle: '大桶大足浴-保安',
num: '2人',
},
{
key: '1.2',
jobTitle: '大桶大足浴-保安',
num: '5人',
},
]
},
{
key: '2',
title: '餐飲酒店/收銀員',
number: '無(wú)門(mén)店,共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: '關(guān)聯(lián)門(mén)店數(shù)',
dataIndex: 'number',
key: 'number',
},
{
title: '時(shí)間',
dataIndex: 'time',
key: 'time',
},
]
const expandedRowRender = (record: any, index: any, indent: any, expanded: any) => {
const childData = record.childData
const childColumns: any = [
{
title: '崗位名稱(chēng)',
dataIndex: 'jobTitle',
key: 'jobTitle'
},
{
title: '招聘人數(shù)',
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>
);
}
四、開(kāi)始配置rowSelection
1、配置父子Table的rowSelection
const childRowSelection = {
selectedRowKeys: childSelectedRowKeys,
onSelect: onChildSelectChange,
onSelectAll: onChildSelectAll
}
const parentRowSelection = {
selectedRowKeys: parentSelectedRowKeys,
onSelect: onParentSelectChange,
onSelectAll: onParentSelectAll,
}
2、創(chuàng)建childSelectedRowKeys,parentSelectedRowKeys變量,用來(lái)存放父子Table選中的key值
const [parentSelectedRowKeys, setParentSelectedRowKeys] = useState<any>([])
const [childSelectedRowKeys, setChildSelectedRowKeys] = useState<any>([])
3、設(shè)置子Table手動(dòng)選擇/取消某行的回調(diào) onChildSelectChange
選擇單個(gè)時(shí),當(dāng)前行選中,若將該Table的所有選項(xiàng)全部選中,則子Table對(duì)應(yīng)的父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會(huì)將其他子Table中選中的key值放到數(shù)組中,但是值為undefined,如:[ undefined,1,uundefined]
selectedRows = selectedRows.filter((a: any) => a !== undefined)
//第二步,判斷selectedRows的長(zhǎng)度是否為data中child的長(zhǎng)度,相等,就將父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、設(shè)置子Table手動(dòng)選擇/取消選擇所有行的回調(diào)onChildSelectAll
當(dāng)選擇全選時(shí),子Table全部選中,并且該子table對(duì)應(yīng)的父table行也選中,取消全選時(shí),子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對(duì)應(yīng)的父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、設(shè)置父Table手動(dòng)選擇/取消某行的回調(diào) onParentSelctChange
當(dāng)選擇父Table某一行時(shí),該行下的子Table全部選中,取消選擇時(shí),該行下的子Table也全部取消選中
const onParentSelectChange = (record: any, selected: any, selectedRows: any) => {
let patentArr: any = [...parentSelectedRowKeys];
let childArr: any = [...childSelectedRowKeys];
//setChildArr:選擇父Table下的所有子選項(xiàng)
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全取消選中(針對(duì)childArr,過(guò)濾掉取消選中的父Table下的所有子Table的key)
patentArr.splice(patentArr.findIndex((item: any) => item === record.key), 1)
childArr = childArr.filter((item: any) => !setChildArr.some((e: any) => e === item))
}
//第三步,設(shè)置父,子的SelectedRowKeys
setParentSelectedRowKeys(patentArr)
setChildSelectedRowKeys(childArr)
}
6、設(shè)置父Table手動(dòng)選擇/取消選擇所有行的回調(diào)onParentSelectAll
全選時(shí),父Table全部選中,所有對(duì)應(yīng)的子Table也全部選中。取消全選時(shí),父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全選中,設(shè)置子Table的SelectedRowKeys
patentArr = Array.from(new Set([...patentArr, ...changeRows.map((item: any) => item.key)]))
setChildSelectedRowKeys(setChildArr)
} else {
//第二步:父Table取消選中,子Table全取消選中,設(shè)置子Table的SelectedRowKeys
patentArr = patentArr.filter((item: any) => !changeRows.some((e: any) => e.key === item))
setChildSelectedRowKeys([])
}
//第三步:設(shè)置父Table的SelectedRowKeys
setParentSelectedRowKeys(patentArr)
}
這樣,父子Table的選擇框聯(lián)動(dòng)就完成了,
注意:dataSource數(shù)據(jù)格式根據(jù)自己的格式而定
五、完整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: '餐飲酒店/服務(wù)員',
number: '8家門(mén)店,共8人',
time: '2020.05.25 15:35',
childData: [
{
key: '1.1',
jobTitle: '大桶大足浴-保安',
num: '2人',
},
{
key: '1.2',
jobTitle: '大桶大足浴-保安',
num: '5人',
},
]
},
{
key: '2',
title: '餐飲酒店/收銀員',
number: '無(wú)門(mén)店,共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: '關(guān)聯(lián)門(mén)店數(shù)',
dataIndex: 'number',
key: 'number',
},
{
title: '時(shí)間',
dataIndex: 'time',
key: 'time',
},
]
const expandedRowRender = (record: any, index: any, indent: any, expanded: any) => {
const childData = record.childData
const childColumns: any = [
{
title: '崗位名稱(chēng)',
dataIndex: 'jobTitle',
key: 'jobTitle'
},
{
title: '招聘人數(shù)',
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下的所有子選項(xiàng)
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))
}
//第三步,設(shè)置父,子的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全選中,設(shè)置子Table的SelectedRowKeys
patentArr = Array.from(new Set([...patentArr, ...changeRows.map((item: any) => item.key)]))
setChildSelectedRowKeys(setChildArr)
} else {
//第二步:父Table取消選中,子Table全取消選中,設(shè)置子Table的SelectedRowKeys
patentArr = patentArr.filter((item: any) => !changeRows.some((e: any) => e.key === item))
setChildSelectedRowKeys([])
}
//第三步:設(shè)置父Table的SelectedRowKeys
setParentSelectedRowKeys(patentArr)
}
const onChildSelectChange = (record: any, selected: any, selectedRows: any) => {
//record:當(dāng)前操作行
//selected選中狀態(tài)
//selectedRows:選擇的數(shù)組
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的長(zhǎng)度是否為data中child的長(zhǎng)度,相等,就將父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:改變的所有數(shù)組
//第一步:判斷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對(duì)應(yīng)的父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以及選擇框聯(lián)動(dòng)操作就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Vue項(xiàng)目在IE瀏覽器的兼容問(wèn)題及解決方法
該文章主要介紹了如何在Vue項(xiàng)目中解決IE瀏覽器的兼容性問(wèn)題,包括解決IE不兼容axios的Promise對(duì)象、ES6語(yǔ)法以及polyfill的使用方法,通過(guò)配置babel-polyfill、es6-promise和轉(zhuǎn)ES5語(yǔ)法,解決了在IE瀏覽器中常見(jiàn)的兼容性問(wèn)題,需要的朋友可以參考下2025-01-01
Vue項(xiàng)目中使用flow做類(lèi)型檢測(cè)的方法
這篇文章主要介紹了Vue項(xiàng)目中使用flow做類(lèi)型檢測(cè)的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03
axios模塊化封裝實(shí)例化及vue本地解決跨域方案
這篇文章主要為大家介紹了axios模塊化封裝實(shí)例化及vue本地解決跨域示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05
Vue子級(jí)如何向父級(jí)傳遞數(shù)據(jù)(自定義事件)
這篇文章主要介紹了Vue子級(jí)如何向父級(jí)傳遞數(shù)據(jù)(自定義事件),具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08
vue動(dòng)態(tài)設(shè)置路由權(quán)限的主要思路
這篇文章主要給大家介紹了關(guān)于vue動(dòng)態(tài)設(shè)置路由權(quán)限的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01
elementUI的table表格改變數(shù)據(jù)不更新問(wèn)題解決
最近在做vue的項(xiàng)目時(shí)發(fā)現(xiàn)了一個(gè)問(wèn)題,今天就來(lái)解決一下,本文主要介紹了elementUI的table表格改變數(shù)據(jù)不更新問(wèn)題解決,感興趣的可以了解一下2022-02-02

