Antd 自定义列表全选功能

背景

需要为List组件自定义全选功能,如下图所示:

在这里插入图片描述

  • 全选checkbox需要与下面每一项的checkbox联动;
  • 当从第一页翻页到第二页的时候,第一页已选的内容保持,可以对第二页勾选,同时保证全选checkbox的状态是正确的。

实现

组件一 SelectAllCheckbox.tsx:

import { Checkbox } from 'antd';
import { t } from 'i18next';
import { forwardRef, useEffect, useImperativeHandle, useState } from 'react';
import TableSelectedDes from '../TableSelectedDes';// rowId必填,跟selectedRowKeys一致
export type CheckBoxItem = { rowId: number } & Record<string, any>;interface Props {data: CheckBoxItem[]; // 当前页的数据limit?: number; // 当前页的page size,默认为20callbackSelectedRowKeys: (values: number[]) => void;
}// 根据当前页的数据,判断当前页已经被选中的项
export const getCurrentCheckedList = (allKeys: number[], currentPageData: CheckBoxItem[]) => {const current: number[] = [];allKeys?.forEach((checkedId) => {currentPageData?.forEach((c: CheckBoxItem) => {if (c.rowId === checkedId) {current.push(checkedId);}});});return current;
};function SelectAllCheckbox(props: Props, ref: any) {const { data, limit = 20, callbackSelectedRowKeys } = props;const [selectedRowKeys, setSelectedRowKeys] = useState<number[]>([]);const [indeterminate, setIndeterminate] = useState(false);const [checkAll, setCheckAll] = useState(false);// 单个checkbox被点击的时候const handleClickItemCheckbox = (isChecked: boolean, clickedId: number) => {let keys;if (isChecked) {keys = selectedRowKeys.filter((key) => key !== clickedId);} else {keys = [...selectedRowKeys, clickedId];}setSelectedRowKeys(keys);const current = getCurrentCheckedList(keys, data);const curLimit = data?.length < limit ? data?.length : limit;setCheckAll(current?.length === curLimit);setIndeterminate(!!current.length && current.length < curLimit);};// 全选checkbox被点击const handleClickAllCheckbox = () => {if (!checkAll) {setSelectedRowKeys(Array.from(new Set([...selectedRowKeys, ...(data?.map((item: CheckBoxItem) => item.rowId) || [])])),);} else {// 比如取消选择第二页的数据,但是还需要保留第一页已选择的数据setSelectedRowKeys(selectedRowKeys.filter((key) => !data?.map((item) => item.rowId)?.includes(key)));}setCheckAll(!checkAll);setIndeterminate(false);};// 取消选择const cancelSelectedAll = () => {setSelectedRowKeys([]);setIndeterminate(false);setCheckAll(false);};// 当切换页数的时候,可能需要重置当前页的全选checkbox状态const handleSetCheckAllStatus = (list: CheckBoxItem[], curLimit?: number) => {const neeLimit = curLimit || limit;const currentPageCheckedList = getCurrentCheckedList(selectedRowKeys, list);setCheckAll(currentPageCheckedList?.length === neeLimit);setIndeterminate(!!currentPageCheckedList.length && currentPageCheckedList.length < neeLimit);};// 父组件可能存在批量操作之类的,比如批量删除所选项之后,需要重新更新selectedRowKeysconst handleUpdateSelectedRowKeys = (keys: number[]) => {setSelectedRowKeys(keys);};useImperativeHandle(ref, () => ({handleClickItemCheckbox,handleSetCheckAllStatus,handleUpdateSelectedRowKeys,}));useEffect(() => {callbackSelectedRowKeys(selectedRowKeys);}, [selectedRowKeys]);return (<><Checkboxstyle={{ marginRight: 5, alignSelf: 'center' }}indeterminate={indeterminate}checked={checkAll}onChange={handleClickAllCheckbox}>{t('shark-select-all')}</Checkbox>{selectedRowKeys?.length > 0 && (<TableSelectedDes selectedRowKeys={selectedRowKeys} cancelSelected={cancelSelectedAll} />)}</>);
}/** 全选Checkbox组件* 1. 支持全选、取消选择* 2. 支持数据翻页时,checkbox正常联动*/
export default forwardRef(SelectAllCheckbox);

组件二 TableSelectedDes.tsx:

import { Button, Space } from 'antd';
import { t } from 'i18next';type Props = {selectedRowKeys: React.Key[];cancelSelected: () => void;
};export default function TableSelectedDes(props: Props) {const { selectedRowKeys = [], cancelSelected } = props;return (<Space size="middle"><p style={{ marginBottom: 0, fontSize: 12 }}>{t('shark-choosed')} {selectedRowKeys?.length} {t('shark-items')}</p><Button style={{ marginLeft: -22, fontSize: 12 }} type="link" onClick={cancelSelected}>{t('shark-deselect')}</Button></Space>);
}

使用

  // 请求数据const getMessageData = async () => {try {// const res = await xxx;if (!res.errmsg) {const newData = res.result.data?.map((item: MessageItem) => ({ ...item, rowId: item.id })); // 关键点,设置rowIdsetData(newData);setTotal(res.result.total);// 关键点// 当翻页时,初始化【全选】选项listBatchRowRef.current?.handleSetCheckAllStatus(newData);}} catch (e) {console.log(e);}};const handleClickItemCheckbox = (isChecked: boolean, clickedId: number) => {listBatchRowRef.current?.handleClickItemCheckbox(isChecked, clickedId);};const renderListItem = (item: MessageItem) => {const { sender, create_time, title, message_status } = item;const time = moment(create_time).format('YYYY-MM-DD HH:mm:ss');const description = (<Row>{time}<span style={{ marginLeft: 10 }}>{sender}</span></Row>);const isChecked = selectedRowKeys?.includes(item.rowId);return (<List.Itemactions={[<Button type="link" style={{ padding: 0 }} onClick={() => handleDetail(item)}>{t('shark-detail')}</Button>,<Button type="link" danger style={{ padding: 0 }} onClick={() => handleDelete(item)}>{t('shark-delete')}</Button>,]}>// 单个项的checkbox框<Checkboxstyle={{ marginRight: 10 }}onChange={() => handleClickItemCheckbox(isChecked, item.rowId)} // 关键点,单个项的点击checked={isChecked}onClick={(e) => e.stopPropagation()} // 阻止点击复选框时,促使折叠面板展开/折叠/><List.Item.Metatitle={<span style={{ color: message_status === MessageType.READ ? 'rgba(0, 0, 0, 0.45)' : '#000' }}>{title}</span>}description={description}/></List.Item>);};// 引用组件
<SelectAllCheckboxdata={data as unknown as CheckBoxItem[]}callbackSelectedRowKeys={setSelectedRowKeys}ref={selectAllCheckboxRef}
/>{/* 消息列表 */}
<ListitemLayout="horizontal"dataSource={data}rowKey="id"pagination={{onChange: (page) => setSearchParams({ ...searchParams, page }),pageSize: 20,current: searchParams.page,total,showTotal: () => `Total ${total} items`,}}loading={loading}className="message-tab-list-container"renderItem={renderListItem}
/>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1451197.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

在自己的电脑上搭建我的世界Java版服务器

很多朋友&#xff0c;喜欢玩Minecraft&#xff0c;也希望搭建一个服务器&#xff0c;用于和小伙伴联机&#xff1b; 并且&#xff0c;拥有服务器后&#xff0c;即使所有玩家都下线&#xff0c;“世界”依旧在运行&#xff0c;玩家可以随时参与其中&#xff0c;说不定一上线&am…

【Da-SimaRPN】《Distractor-aware Siamese Networks for Visual Object Tracking》

ECCV-2018 中科大 文章目录 1 Background and Motivation2 Related Work3 Advantages / Contributions4 Method4.1 Features and Drawbacks in Traditional Siamese Networks4.2 Distractor-aware Training4.3 Distractor-aware Incremental Learning4.4 DaSiamRPN for Long-t…

mmap引起的内存泄漏分析

最近遇到一个内存泄漏问题&#xff0c;由于问题出现在客户端&#xff0c;只能通过客户提供的Log来分析。 根据客户提供的/proc/meminfo数据发现&#xff0c;MemAvailable 由294072kB减小至18128kB&#xff0c;减小约269MB&#xff0c;引起该变化的最直接原因是PageTables由614…

49.Chome浏览器有三种清缓存方式

49.Chome浏览器有三种清缓存方式&#xff1a;正常重新加载、硬件重新加载、清空缓存并硬性重新加载 1、【正常重新加载】 触发方式&#xff1a;①F5  ②CtrlR  ③在地址栏上回车  ④点击链接 如果缓存不过期会使用缓存。这样浏览器可以避免重新下载JavaScript文件、图像、…

kettle从入门到精通 第六十九课 ETL之kettle kettle cdc mysql,轻松实现增量同步

1、之前kettle cdc mysql的时候使用的方案是canalkafkakettle&#xff0c;今天我们一起学习下使用kettle的插件Debezium直接cdc mysql。 注&#xff1a;CDC (Change Data Capture) 是一种技术&#xff0c;用于捕获和同步数据库中的更改。 1&#xff09;Debezium步骤解析mysql b…

反贿赂管理体系认证:提升企业诚信与防范风险的双重利器

反贿赂管理体系认证在当今商业环境中发挥着至关重要的作用。这一认证不仅有助于提高企业的道德标准和社会责任感&#xff0c;还能有效防范商业风险&#xff0c;并提升内部管理水平和工作效率。 反贿赂管理体系认证要求企业制定和执行严格的反贿赂政策和程序&#xff0c;从而在…

计算机网络原理实验(7):分析IP报文结构

一、实验名称 分析IP报文结构 二、实验目的&#xff1a; 1.掌握使用Wireshark分析俘获trace文件的基本技能&#xff1b; 2.深刻理解IP报文结构和工作原理。 三、实验内容和要求 1.分析俘获的分组&#xff1b; 2.分析IP报文结构。 3.记录每一字段的值&#xff0c;分析它的作…

FL Studio(FL 21)软件下载-详细安装教程视频

​fl studio 编曲软件即,简称FL,是音乐人熟知的水果编曲软件.可以完成完整的音乐制作环境或数字音频工作站(DAW)就是大家熟悉的水果 编曲软件&#xff0c;一个全能的音乐制作软件&#xff0c;包括编曲、录音、剪辑和混音等诸多功能&#xff0c;让你的电脑编程一个全能的录音室。…

基坑监测:关键环节与深入剖析,保障施工安全与质量新标准

在建筑工程中&#xff0c;基坑监测是一项至关重要的工作&#xff0c;它涉及对基坑施工现场的实时监测数据进行分析和评估&#xff0c;以确保基坑施工活动的稳定、安全和高效进行。基坑监测涵盖地质勘探、基坑开挖、加固、支护、周边环境以及工程质量验收等多个环节&#xff0c;…

通信原理抽样定理和PAM调制解调硬件实验

一、实验目的 1. 加深理解抽样定理&#xff1b; 2. 加深理解脉冲幅度调制的原理。 二、实验内容 1. 观测PAM平顶抽样波形&#xff1b; 2. 观测PAM自然抽样波形及解码后波形。 三、实验器材 1. 双踪示波器&#xff1b; 2. 通信原理实验箱信号源模块、①号模块。 四、实…

文章解读与仿真程序复现思路——电工技术学报EI\CSCD\北大核心《基于广义目标级联法的多牵引变电站 光伏-储能协同规划配置》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…

java写一个验证码

生成验证码 内容&#xff1a;可以是小写字母&#xff0c;也可以是大写字母&#xff0c;还可以是数字 规则 长度为5 内容中是四位字母&#xff0c;1位数字。 其中数字只有1位&#xff0c;但是可以出现在任意的位置。 package User;import java.util.ArrayList; import jav…

FlashDB的TS数据库的标准ANSI C移植验证

本文目录 1、引言2、环境准备3、修改驱动4、验证 文章对应视频教程&#xff1a; 暂无&#xff0c;可以关注我的B站账号等待更新。 点击图片或链接访问我的B站主页~~~ 1、引言 在当今数据驱动的时代&#xff0c;高效可靠的数据存储与管理对于嵌入式系统及物联网(IoT)应用至关重…

【Unity每日一记】FairyGUI为什么能自动生成代码,它的好处是什么

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;uni…

kali中安装zsteg教程

1、下载文件 git clone http://www.github.com/zed-0xff/zsteg 2、第一步需要保证虚拟机是有网络的&#xff0c;不然无法克隆 3、可以将网络设置成如下后重启&#xff0c;访问百度看看能不能访问&#xff0c;若可以访问&#xff0c;则进行下一步 4、查看源&#xff0c;删除源&…

OpenAI把GPT-4原始版给了他们:研究不微调只靠提示词能走多远

除了OpenAI自己&#xff0c;居然还有别人能用上GPT-4-Base版&#xff1f;&#xff1f; 也就是未经微调的预训练版&#xff0c;还不会对话聊天&#xff0c;只会补全句子的模型。 EPFL&#xff08;瑞士洛桑联邦理工&#xff09;团队申请到了访问权限&#xff0c;用于研究**“上…

逆向分析-Ollydbg动态跟踪Ransomware.exe恶意锁机程序

1.认识Ollydbg Ollydbg是一个新的动态追踪工具&#xff0c;将IDA与SoftICE结合起来的思想&#xff0c;Ring 3级调试器&#xff0c;非常容易上手&#xff0c;己代替SoftICE成为当今最为流行的调试解密工具了。同时还支持插件扩展功能&#xff0c;是目前最强大的调试工具。 Oll…

我的创作纪念日(1825天)

Ⅰ、机缘 1. 记得是大一、大二的时候就听学校的大牛说&#xff0c;可以通过写 CSDN 博客&#xff0c;来提升自己的代码和逻辑能力&#xff0c;虽然即将到了写作的第六个年头&#xff0c;但感觉这句话依旧受用; 2、今年一整年的创作都没有停止&#xff0c;本年度几乎是每周都来…

FuTalk设计周刊-Vol.037

&#x1f525;AI漫谈 热点捕手 1、最全攻略&#xff01;OpenAI 发布 GPT-4 使用指南&#xff0c;所有干货全在这 OpenAI 官方发布了 GPT-4 使用指南 Prompt engineering&#xff0c;这里面记载了驾驭 GPT-4 的六大策略。 链接https://www.ifanr.com/1570792 2、Midjourney V…

平安科技智能运维案例

平安科技智能运维案例 在信息技术迅速发展的背景下&#xff0c;平安科技面临着运维规模庞大、内容复杂和交付要求高等挑战。通过探索智能运维&#xff0c;平安科技建立了集中配置管理、完善的运营管理体系和全生命周期运维平台&#xff0c;实施了全链路监控&#xff0c;显著提…