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完整代碼

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM