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)
}
相关推荐
Boilermaker19926 分钟前
【Java EE】SpringIoC
前端·数据库·spring
中微子18 分钟前
JavaScript 防抖与节流:从原理到实践的完整指南
前端·javascript
天天向上102433 分钟前
Vue 配置打包后可编辑的变量
前端·javascript·vue.js
芬兰y1 小时前
VUE 带有搜索功能的穿梭框(简单demo)
前端·javascript·vue.js
好果不榨汁1 小时前
qiankun 路由选择不同模式如何书写不同的配置
前端·vue.js
小蜜蜂dry1 小时前
Fetch 笔记
前端·javascript
拾光拾趣录1 小时前
列表分页中的快速翻页竞态问题
前端·javascript
小old弟1 小时前
vue3,你看setup设计详解,也是个人才
前端
Lefan1 小时前
一文了解什么是Dart
前端·flutter·dart
Patrick_Wilson1 小时前
青苔漫染待客迟
前端·设计模式·架构