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 相关文章推荐
JS 判断undefined的实现代码
Nov 26 Javascript
javascript控制swfObject应用介绍
Nov 29 Javascript
JS的千分位算法实现思路
Jul 31 Javascript
jQuery中element选择器用法实例
Dec 29 Javascript
通过Jquery.cookie.js实现展示浏览网页的历史记录超管用
Oct 23 Javascript
Bootstrap每天必学之标签页(Tab)插件
Aug 09 Javascript
Google 地图API资料整理及详细介绍
Aug 06 Javascript
利用Angularjs和Bootstrap前端开发案例实战
Aug 27 Javascript
微信小程序 解决请求服务器手机预览请求不到数据的方法
Jan 04 Javascript
mint-ui在vue中的使用示例
Apr 05 Javascript
Vue源码解读之Component组件注册的实现
Aug 24 Javascript
JS 自执行函数原理及用法
Aug 05 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
用phpmyadmin更改mysql5.0登录密码
2008/03/25 PHP
Ajax和PHP正则表达式验证表单及验证码
2016/09/24 PHP
php 实现Hash表功能实例详解
2016/11/29 PHP
实例讲解PHP表单处理
2019/02/15 PHP
浅谈php使用curl模拟多线程发送请求
2019/03/08 PHP
PHP使用观察者模式处理异常信息的方法详解
2019/09/24 PHP
jquery中实现简单的tabs插件功能的代码
2011/03/02 Javascript
放弃用你的InnerHTML来输出HTML吧 jQuery Tmpl不详细讲解
2013/04/20 Javascript
jQuery实现可拖动的浮动层完整代码
2013/05/27 Javascript
浅谈javascript的Array.prototype.slice.call
2015/08/31 Javascript
js中获取时间new Date()的全面介绍
2016/06/20 Javascript
JS实现预加载视频音频/视频获取截图(返回canvas截图)
2017/10/09 Javascript
vue 设置proxyTable参数进行代理跨域
2018/04/09 Javascript
vue使用ElementUI时导航栏默认展开功能的实现
2018/07/04 Javascript
Vuex 使用 v-model 配合 state的方法
2018/11/13 Javascript
详解puppeteer使用代理
2018/12/27 Javascript
在Angular项目使用socket.io实现通信的方法
2021/01/05 Javascript
构建Python包的五个简单准则简介
2015/06/15 Python
Python编程实现的图片识别功能示例
2017/08/03 Python
Tornado 多进程实现分析详解
2018/01/12 Python
python线程池threadpool实现篇
2018/04/27 Python
Python minidom模块用法示例【DOM写入和解析XML】
2019/03/25 Python
搞定这套Python爬虫面试题(面试会so easy)
2019/04/03 Python
vscode 配置 python3开发环境的方法
2019/09/19 Python
jupyternotebook 撤销删除的操作方式
2020/04/17 Python
Pat McGrath Labs官网:世界上最有影响力的化妆师推出的彩妆品牌
2018/01/07 全球购物
在C#中如何实现多态
2014/07/02 面试题
企业门卫岗位职责
2013/12/12 职场文书
教师求职信怎么写
2015/03/20 职场文书
三方合作意向书范本
2015/05/09 职场文书
2015年防汛工作总结
2015/05/15 职场文书
入党积极分子党小组意见
2015/06/02 职场文书
阳光体育运动标语口号
2015/12/26 职场文书
《祁黄羊》教学反思
2016/02/20 职场文书
经典格言警句:没有热忱,世间便无进步
2019/11/13 职场文书
CSS 圆形进度栏
2021/04/06 HTML / CSS