react基于ag-gird封装弹窗(多选/单选)
功能
- 弹窗
- ag-gird
- 数据集/已选择
- 查询
- 单选/多选
- 选中本页/选中全部
- 移除/移除全部
页面代码
- 使用
ini
//多选
<Form.Item label="店铺" name="shop">
<ShopChooseInput mulitip />
</Form.Item>
//单选
<Form.Item label="店铺" name="shop">
<ShopChooseInput mulitip={false} />
</Form.Item>
2.传递参数(定义数据类型)
typescript
interface valueProp {
name: string;
id: string;
[key: string]: any;
}
interface receiveParams {
cRef?: any;
mulitip: Boolean;
children?: ReactElement | any;
value?: valueProp[];
onChange?: (data: { [key: string]: any } | Array<any> | null) => void;
}
3.props.children
判断是否传递children,没有则使用默认内容
ini
{props?.children ? (
<div onClick={() => toggleModal(true)}>{props.children}</div>
) : (
<Input
onClick={() => toggleModal(true)}
value={
!!props?.mulitip
? tempCheckedData.current?.length > 0
? tempCheckedData.current?.length + "条数据"
: undefined
: tempCheckedData.current?.length > 0
? tempCheckedData.current?.[0]?.name
: undefined
}
placeholder="请选择"
readOnly
className="input"
style={{ width: "200px" }}
/>
)}
4.弹窗
ini
<Modal
title='店铺'
open={visible}
onCancel={() => toggleModal(false)}
destroyOnClose
keyboard
width={1200}
wrapClassName="modal"
maskClosable={false}
footer={
<>
<Button type="primary" onClick={() => ensureCheckedData()}>
确认选择
</Button>
<Button onClick={() => toggleModal(false)}>取消</Button>
</>
}
>
</Modal>
5.弹窗内容 根据props.mulitip判断是多选还是单选,因为有2个tab,根据showChecked判断是否展示搜索内容,选择全部按自己需求自己选择是否展示
ini
{props.mulitip && (
<Tabs onChange={tabChangeEvent}>
<Tabs.TabPane tab="数据集" key="list"></Tabs.TabPane>
<Tabs.TabPane tab="已选择" key="checked"></Tabs.TabPane>
</Tabs>
)}
{!showChecked && (
<div className="search-box">
<Form form={form} layout="inline">
<Form.Item label="速查" name="keyword">
<Input
allowClear
style={{ width: 200 }}
placeholder="请输入"
onPressEnter={() => getListData()}
/>
</Form.Item>
<Form.Item>
<Button
type="primary"
className="margin-l10"
onClick={() => getListData()}
>
查询
</Button>
<Button
onClick={() => resetRequest()}
style={{ marginLeft: 10 }}
>
重置
</Button>
</Form.Item>
</Form>
</div>
)}
{props.mulitip && (
<div className="pinduoduo-libary-handleBtns">
{showChecked ? (
<>
<Button
type="primary"
danger
ghost
onClick={() => delCheckedTableData()}
>
移除全部
</Button>
</>
) : (
<>
<Button
type="primary"
ghost
onClick={() => checkedCurPageAll()}
>
选中本页
</Button>
{/* {showGetAllDataBtn && (
<Button
type="primary"
onClick={() => getAllDataAndChecked()}
ghost
>
选中全部
</Button>
)} */}
</>
)}
</div>
)}
6.数据列表
ini
{!showChecked && (
<>
<div className="pinduoduo-libary-table ag-theme-alpine">
{loading && (
<div className="customLoading">
<Spin tip="数据搜索中,请稍后" size="large" />
</div>
)}
<AgGrid
ref={gridRef}
overlayNoRowsTemplate="无数据"
overlayLoadingTemplate="加载中"
rowData={tableData}
columnDefs={tableGridDefine}
rowHeight={70}
suppressCopyRowsToClipboard
suppressMoveWhenRowDragging
rowSelection={props.mulitip ? "multiple" : "single"}
{...(props.mulitip
? {
rowMultiSelectWithClick: true,
onRowSelected: checkedDataEvent,
}
: {})}
defaultColDef={{
resizable: true,
}}
/>
</div>
<div className="pinduoduo-libary-pagination">
<Pagination
showQuickJumper
onChange={onPaginationChange}
showTotal={(total, range) => (
<span>
第{range[0]} - {range[1]}条,共 {total} 条
</span>
)}
total={pagination.total}
pageSize={pagination.size}
current={pagination.current}
/>
</div>
</>
)}
7.选中数据
ini
{/* 选中的数据 */}
{showChecked && (
<div className="pinduoduo-libary-table">
<AgGrid
rowData={checkedList}
paginationPageSize={20}
pagination
rowMultiSelectWithClick
columnDefs={[
...tableGridDefine,
{
headerName: "操作",
field: "actions",
pinned: "right",
width: 100,
cellRenderer: ({ data }: ICellRendererParams) => {
return (
<Button
type="link"
danger
onClick={() => delCheckedTableData(data)}
>
移除
</Button>
);
},
},
]}
rowHeight={70}
suppressMoveWhenRowDragging
defaultColDef={{
resizable: true,
}}
/>
</div>
)}
逻辑代码
- 搜索我们使用antd的Form
css
const [form] = Form.useForm();
- 支持ref点击打开弹窗
scss
//暴露出当前组件的方法以便父组件调用
useImperativeHandle(props.cRef, () => ({
toggleModal,
}));
3.打开弹窗
typescript
const toggleModal = async (value: boolean, checkeds?: Array<any>|any) => {
//隐藏显示弹窗事件
setVisible(value);
if (value) {
const checkedArray = Array.isArray(checkeds)
? checkeds
: checkeds
? [checkeds]
: [];
const propsValueArray = Array.isArray(props?.value)
? props?.value
: props?.value
? [props?.value]
: [];
const data = checkedArray.length > 0 ? checkedArray : propsValueArray;
// 判断是通过ref还是props传递过来的
tempCheckedData.current = data;
}
resetRequest();
return Promise.resolve(true);
};
const resetRequest = () => {
//重置查询
form.resetFields();
//请求数据
getListData({
current: 1,
});
};
const getListData = async()=>{
***请求数据***
resetTableCheckStatus();
}
const resetTableCheckStatus = () => {
//当前页表格数据添加选中或者取消选中的效果
setTimeout(() => {
const api = gridRef?.current?.api;
if (!api) return;
const checkedIds: Array<string> = tempCheckedData.current.map(
(item: any) => item.id
);
api.forEachNode((node: any) => {
node.setSelected(checkedIds.includes(node.data.id) ? true : false);
});
}, 200);
};
4.切换tab
ini
const tabChangeEvent = (value: string) => {
//切换tab
const isChecked: boolean = value === "checked" ? true : false;
setShowChecked(isChecked);
if (!isChecked) {
resetTableCheckStatus();
} else {
setCheckedList(tempCheckedData.current);
}
};
5.删除
ini
const delCheckedTableData = (delRowData?: any) => {
//移除已选中表格中的数据
//如果delRowData不存在则删除全部的选中
let newCheckedList: Array<any> = [];
if (delRowData?.id) {
newCheckedList = tempCheckedData.current.filter(
(item: any) => item.id !== delRowData.id
);
}
tempCheckedData.current = newCheckedList;
setCheckedList(newCheckedList);
};
6.选择本页
typescript
const checkedCurPageAll = (checkData?: Array<any>) => {
//选中本页的全部数据
const api = gridRef?.current?.api;
if (!api) return;
let curPageDatas = checkData || (api ? getAgGridData(api) : []);
const checkedIds: Array<string> = curPageDatas.map((item: any) => item.id);
api.forEachNode((node: any) => {
node.setSelected(checkedIds.includes(node.data.id) ? true : false);
});
};
7.表格选择
ini
const checkedDataEvent = ({ data, node }: any) => {
//选中表格的数据
if (!data?.id) return;
const curCheckIds = tempCheckedData.current.map((item: any) => item.id);
const includeIndex = curCheckIds.indexOf(data.id);
if (node.isSelected()) {
if (includeIndex === -1) tempCheckedData.current.push(data);
} else {
tempCheckedData.current.splice(includeIndex, 1);
}
};
8.翻页
ini
const onPaginationChange = (page: number, pageSize: number) => {
//翻页事件
setTableData([]);
getListData({
current: pageSize === pagination.size ? page : 1,
size: pageSize,
});
};
9.确认弹窗
ini
const ensureCheckedData = () => {
//确认已选择的数据
if (props.mulitip) {
if (!tempCheckedData.current.length) {
message.warning("您暂未选择店铺");
return;
}
props.onChange &&
props?.onChange(JSON.parse(JSON.stringify(tempCheckedData.current)));
} else {
const api = gridRef?.current?.api;
if (!api) return;
const selectRows: Array<any> = api.getSelectedRows();
if (!selectRows.length) {
message.warning("您暂未选择店铺");
return;
}
props.onChange && props?.onChange(selectRows[0]);
tempCheckedData.current = [selectRows[0]];
}
toggleModal(false);
};
10.选择全部
scss
const getAllDataAndChecked = async()=>{
***请求数据***
//resDat为请求的数据
checkedCurPageAll(resData)
}