07月12, 2021

关于Antd Table组件selectRows 翻页后不保留上一页已选items的解决方案 (v4版本)

关于Antd Table组件selectRows 翻页后不保留上一页已选items的解决方案

问题描述:

在用antd Table组件写一个产品选择框的时候,遇到antd Table组件的selectedRows在翻页后再勾选新的item,不会保留上一页已勾选的item,而是基于当前页面的dataSource重新记录当前的勾选项.

w100

切换分页的时候,需要保留上一页已选的状态.

解决方案:

于是又去仔细查看antd Table组件的官方文档,发现两个可以用得上的API,叫做onSelectonSelectAll.需要自己手动去写选中和取消选中的方法.

w100;

首先我们可以看到onSelect需要传入一个函数作为回调,然后这个方法的参数里有record, selected, selectedRows这几项(nativeEvent原生事件我不关心),经过测试后确定:

1、record就是当前操作(选中或取消选中)的item
2、selected是个布尔值,true代表本次是选中操作,false就是取消选中
3、selectedRows是一个数组,就是当前已选择的items(没有跨页的记录)

至于onSelectAll,是在点击全选和取消全选时触发的回调函数,截图中也可以看到,它有selected, selectedRows, changeRows这三个参数:

1、selected,同上,true全选,false取消全选
2、selectedRows,也同上,当前已选择的items(没有跨页的记录)
3、changeRows,这个可就优秀了,它就是你的全选/取消全选操作引起变化的items数组,打个比方,如果一页10个,你一个都没选呢,点全选,就会新选择10个,那么changeRows就是这10条数据,如果你已经选了6条,你又点了全选,那么就相当于你又一次性选了4条,那么changeRows就是这4条

引入lodash库文件 (去重)

import { uniqBy } from 'lodash';

定义的status

// 选项的id集合
const [selectedRowKeys, setSelectedRowKeys] = useState([]);
// 选项集合
const [selectedRowsData, setSelectedRows] = useState([]);

const {
    groupList,
    selectDiaVisible,
    handleDialoghide,
    onRadioChange,
  } = props;

  useEffect(() => {
    // 选择客群集合
    setSelectedRowKeys([].concat(groupList));
  }, [groupList, selectDiaVisible]);
 // 单条选中/取消选中方法
 const onSelect = (record, selected, selectedRows) => {
    console.log('result selectedRows', record, selected, selectedRows);
    const {id} = record;
    if (selected) {   //单条选中
      setSelectedRows(selectedRowsData.concat([record]));
      setSelectedRowKeys(selectedRowKeys.concat([id]).filter(Boolean));

    } else {   // 单条取消选中
      console.log('result selectedRows', selectedRowKeys.filter((item) => {
        return item !== id
      }));
      setSelectedRows(selectedRowsData.filter((item) => {
        return item && (item.id !== id);
      }));
      setSelectedRowKeys(selectedRowKeys.filter((item) => {
        return item !== id;
      }).filter(Boolean))
    }
    // 将选中的值传递出去
    onRadioChange(selectedRows);
  }

// 全选/取消全选方法
  const onSelectAll = (selected, sRows, cRows) => {
    console.log('selected, selectedRows, changeRows', selected, sRows, cRows)
    const tmparr = [];
    for (let i = 0; i < cRows.length; i++) {
      tmparr.push(cRows[i].id);
    }
    const AllRows = sRows.filter(Boolean).map(item => { return item });
    const AllIds = sRows.filter(Boolean).map(item => { return item.id });

    if (selected) { // 全选操作
      setSelectedRows(uniqBy(selectedRowsData.concat(AllRows), 'id'));
      setSelectedRowKeys(Array.from(new Set(selectedRowKeys.concat(AllIds))));

    } else {  // 取消全选操作

      let cIds = new Set(tmparr);
      let sIds = new Set(selectedRowKeys);
      setSelectedRows(
        [...selectedRowsData].filter((x) => [...cRows].every((y) => y.id !== x.id))
      );
      setSelectedRowKeys(Array.from(new Set([...sIds].filter((x) => !cIds.has(x)))));

    }
    // 将选中的选项值传递到外层父组件
    onRadioChange(AllRows);
  }

 const handleOk = () => {
    props.setCustomerGroupVal(selectedRowKeys).filter(Boolean);
  }

当你选中其中的某一项的时候,然后在执行全选操作,就会有重复的数据被选中了,对于重复的数据要进行去重处理下.

最后在Table组件调用的时候,rowSelection属性传入这两个方法:

    rowSelection={{
          type: 'checkbox',
          onSelect: onSelect,
          onSelectAll: onSelectAll,
          selectedRowKeys: selectedRowKeys
    }}

外层父组件关键代码

import SelectNews from '../../components/SelectNews'
const [form] = Form.useForm();
const [selectCus, setSelectCus] = useState([]);
const [selectDiaVisible, setSelectDiaVisible] = useState(false);
const handleDialoghide = () => {
    setSelectDiaVisible(false)
  }
// 选中复选框改变事件
 const onRadioChange = (val) => {
    setSelectCus([].concat([...selectCus, ...val]));
 }
const setCustomerGroupVal = (srowKeys) => {
    // 表单赋值
    form.setFieldsValue({
      customerGroupIdList: srowKeys
    });
    handleDialoghide();
  }

  const dialogObj = {
    groupList: form.getFieldValue('customerGroupIdList'),
    selectDiaVisible,
    handleDialoghide,
    onRadioChange,
    setCustomerGroupVal,
  }

return (
    <Fragment>
      <Form
        style={{ width: '100%', marginTop: 50 }}
        name="addPushConfigform"
        form={form}
        labelAlign="right"
        labelCol={{ span: 4 }}
        onFinish={onHandleSubmit}
      >
        <Row>
          <Col span={18}>
            <Form.Item
              name="customerGroupIdList"
              label="客群选择"
            >
              <Select
                style={{ width: '80%' }}
                placeholder="请选择客群"
                mode="multiple"
                open={false}
                onChange={(val) => {
                  // groupListValchange(val);
                  // getGroupDetailsById(val, false);
                }}
              >
                {selectCus.length > 0 &&
                  selectCus.map((item) => {
                    return (
                      <Option value={item.id} key={item.id}>
                        {item.title}
                      </Option>
                    );
                  })}
              </Select>
            </Form.Item>
            <Button
              className="select-btn"
              type="primary"
              style={{ minWidth: 45, padding: '0 10px', position: "absolute", top: 0, right: 0 }}
              onClick={() => {
                setSelectDiaVisible(true);
                props.dispatch(getNewsListByParams({ page: 1, pageSize: 5 }));
              }
              }
            >
              选择
            </Button>
          </Col>
        </Row>
      </Form>
      {selectDiaVisible && <SelectNews {...dialogObj}></SelectNews>}
    </Fragment>
  )

w100

另外,测试了下,如果是单选按钮的话,之前选中的数据,切换分页是没有问题的.可以直接使用 onChange方法.
w100

这样就可以保证在切换分页的时候,之前选中的就不会丢失,可以解决跨页选择的问题了.

本文链接:https://901web.com/post/antd-table-selectedRows-pagination.html

-- EOF --

Comments

请在后台配置评论类型和相关的值。