zoukankan      html  css  js  c++  java
  • 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',
              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

    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>
      );
    }
    Table嵌套Table完整代码
  • 相关阅读:
    eslint 屏蔽html的检查
    css 自定义悬浮窗写法
    echarts象形图图例显示问题
    win10上rocketMQ的部署过程
    死锁以及如何避免死锁
    volatile的一个例子-通俗易懂
    Java四种引用类型
    记录下:安全|API接口安全性设计(防篡改和重复调用)
    了解聚集索引,非聚集索引,联合索引,索引覆盖
    mybatis 查询树形结构
  • 原文地址:https://www.cnblogs.com/minorf/p/13070677.html
Copyright © 2011-2022 走看看