关于Antd Table组件selectRows 翻页后不保留上一页已选items的解决方案
问题描述:
在用antd Table
组件写一个产品选择框的时候,遇到antd Table
组件的selectedRows
在翻页后再勾选新的item,不会保留上一页已勾选的item,而是基于当前页面的dataSource重新记录当前的勾选项.
切换分页的时候,需要保留上一页已选的状态.
解决方案:
于是又去仔细查看antd Table组件的官方文档,发现两个可以用得上的API,叫做onSelect
和onSelectAll
.需要自己手动去写选中和取消选中的方法.
;
首先我们可以看到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>
)
另外,测试了下,如果是单选按钮的话,之前选中的数据,切换分页是没有问题的.可以直接使用
onChange
方法.
这样就可以保证在切换分页的时候,之前选中的就不会丢失,可以解决跨页选择的问题了.
Comments
请在后台配置评论类型和相关的值。