react基于ag-gird封装弹窗(多选/单选)

react基于ag-gird封装弹窗(多选/单选)

功能

  • 弹窗
  • ag-gird
  • 数据集/已选择
  • 查询
  • 单选/多选
  • 选中本页/选中全部
  • 移除/移除全部

页面代码

  1. 使用
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>
 )}

逻辑代码

  1. 搜索我们使用antd的Form
css 复制代码
    const [form] = Form.useForm();
  1. 支持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)
}
相关推荐
J不A秃V头A36 分钟前
Vue3:编写一个插件(进阶)
前端·vue.js
光影少年1 小时前
usemeno和usecallback区别及使用场景
react.js
司篂篂1 小时前
axios二次封装
前端·javascript·vue.js
姚*鸿的博客1 小时前
pinia在vue3中的使用
前端·javascript·vue.js
宇文仲竹2 小时前
edge 插件 iframe 读取
前端·edge
Kika写代码2 小时前
【基于轻量型架构的WEB开发】【章节作业】
前端·oracle·架构
天下无贼!3 小时前
2024年最新版Vue3学习笔记
前端·vue.js·笔记·学习·vue
Jiaberrr3 小时前
JS实现树形结构数据中特定节点及其子节点显示属性设置的技巧(可用于树形节点过滤筛选)
前端·javascript·tree·树形·过滤筛选
赵啸林3 小时前
npm发布插件超级简单版
前端·npm·node.js
我码玄黄4 小时前
THREE.js:网页上的3D世界构建者
开发语言·javascript·3d