Antd的Table组件嵌套Table以及选择框联动操作


Posted in Javascript onOctober 24, 2020

一、需求

在使用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以及选择框联动操作就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
说明你的Javascript技术很烂的五个原因
Apr 26 Javascript
Extjs中TabPane如何嵌套在其他网页中实现思路及代码
Jan 27 Javascript
使用node.js 制作网站前台后台
Nov 13 Javascript
javascript中Object使用详解
Jan 26 Javascript
js实现内容显示并使用json传输数据
Mar 16 Javascript
JS简单测试循环运行时间的方法
Sep 04 Javascript
详谈jQuery unbind 删除绑定事件 / 移除标签方法
Mar 02 Javascript
Vue2.0父子组件传递函数的教程详解
Oct 16 Javascript
微信小程序自动客服功能
Nov 02 Javascript
Vue.js与 ASP.NET Core 服务端渲染功能整合
Nov 16 Javascript
原生js实现获取form表单数据代码实例
Mar 27 Javascript
layui动态绑定事件的方法
Sep 20 Javascript
解决Antd 里面的select 选择框联动触发的问题
Oct 24 #Javascript
ant-design-vue中的select选择器,对输入值的进行筛选操作
Oct 24 #Javascript
jquery插件懒加载的示例
Oct 24 #jQuery
在react-antd中弹出层form内容传递给父组件的操作
Oct 24 #Javascript
Antd下拉选择,自动匹配功能的实现
Oct 24 #Javascript
在react项目中使用antd的form组件,动态设置input框的值
Oct 24 #Javascript
Vue-Ant Design Vue-普通及自定义校验实例
Oct 24 #Javascript
You might like
DC漫画《蝙蝠侠和猫女》图透 猫女怀孕老爷当爹
2020/04/09 欧美动漫
php录入页面中动态从数据库中提取数据的实现
2006/10/09 PHP
PHP删除数组中的特定元素的代码
2012/06/28 PHP
smarty内置函数foreach用法实例
2015/01/22 PHP
php使用gettimeofday函数返回当前时间并存放在关联数组里
2015/03/19 PHP
PHP生成图像验证码的方法小结(2种方法)
2016/07/18 PHP
php设计模式之抽象工厂模式分析【星际争霸游戏案例】
2020/01/23 PHP
让任务管理器中的CPU跳舞的js代码
2008/11/01 Javascript
Javascript Tab 导航插件 (23个)
2009/06/11 Javascript
window.name代替cookie的实现代码
2010/11/28 Javascript
js 限制数字 js限制输入实现代码
2012/12/04 Javascript
Javascript图像处理思路及实现代码
2012/12/25 Javascript
不使用jquery实现js打字效果示例分享
2014/01/19 Javascript
jQuery实现浮动层随浏览器滚动条滚动的方法
2015/09/22 Javascript
Vue过滤器的用法和自定义过滤器使用
2017/02/08 Javascript
详解使用create-react-app快速构建React开发环境
2018/05/16 Javascript
详解基于Vue,Nginx的前后端不分离部署教程
2018/12/04 Javascript
详解NodeJS Https HSM双向认证实现
2019/03/12 NodeJs
JavaScript动态检测密码强度原理及实现方法详解
2019/06/11 Javascript
详解JavaScript 浮点数运算的精度问题
2019/07/23 Javascript
JavaScript面向对象中接口实现方法详解
2019/07/24 Javascript
angular异步验证防抖踩坑实录
2019/12/01 Javascript
[01:03:50]DOTA2-DPC中国联赛 正赛 CDEC vs DLG BO3 第二场 2月7日
2021/03/11 DOTA
python解析中国天气网的天气数据
2014/03/21 Python
matplotlib绘制符合论文要求的图片实例(必看篇)
2017/06/02 Python
python生成九宫格图片
2018/11/19 Python
pygame游戏之旅 添加游戏暂停功能
2018/11/21 Python
python__name__原理及用法详解
2019/11/02 Python
Python字符串格式化输出代码实例
2019/11/22 Python
tensorflow下的图片标准化函数per_image_standardization用法
2020/06/30 Python
python如何快速拼接字符串
2020/10/28 Python
用python 绘制茎叶图和复合饼图
2021/02/26 Python
美国女鞋品牌:naturalizer(娜然)
2016/08/01 全球购物
Wolford法国官网:奥地利奢侈内衣品牌
2020/08/11 全球购物
职工运动会邀请函
2014/01/19 职场文书
考试作弊检讨书
2015/01/27 职场文书