【Antd】封装Table的自定义筛选组件

前言

TDesign的Table组件默认支持input筛选,但是Antdesign并没有,需要通过filterDropdown自定义筛选

在这里插入图片描述

封装filterDropdown

接收两个参数

  • type:使用什么方式筛选
  • placeholder:Input或RangePicker组件的placeholder
import React from "react"
import { SearchOutlined } from "@ant-design/icons"
import { Button, Input, Space, DatePicker } from "antd"
const { RangePicker } = DatePicker

const getFilterDropdown =
  (type, placeholder) =>
  ({ setSelectedKeys, selectedKeys, confirm, clearFilters }) => {
    if (type === "input") {
      return (
        <div style={{ padding: 8 }}>
          <Input
            placeholder={placeholder}
            value={selectedKeys[0]}
            onChange={(e) =>
              setSelectedKeys(
                e.target.value ? [e.target.value, "InputTableFilter"] : []
              )
            }
            onPressEnter={() => confirm()}
            style={{ marginBottom: 8, display: "block" }}
          />
          <Space>
            <Button
              type="primary"
              onClick={() => confirm()}
              icon={<SearchOutlined />}
              size="small"
            >
              搜索
            </Button>
            <Button
              onClick={() => {
                clearFilters?.()
                setSelectedKeys([])
                confirm()
              }}
              size="small"
            >
              重置
            </Button>
          </Space>
        </div>
      )
    }

    // 日期范围选择器的筛选
    if (type === "time") {
      const handleDateChange = (_dates, dateStrings) => {
        setSelectedKeys(
          dateStrings.length ? [...dateStrings, "DateTableFilter"] : []
        )
        confirm()
      }

      return (
        <div style={{ padding: 8 }}>
          <RangePicker
            onChange={handleDateChange}
            showTime
            format="YYYY-MM-DD HH:mm:ss"
          />
        </div>
      )
    }

    return null // 确保在 type 不为 input 或 time 时有返回值
  }

export default getFilterDropdown

返回筛选结果时会在列表末尾插入一个标识,如input对应InputTableFilter、time对应DateTableFilter,这个标识用于确认是否由自定义筛选触发以及采用何种自定义筛选方式。

使用时

filterDropdown: getFilterDropdown("input", "请输入检索条件进行查询")
filterDropdown: getFilterDropdown("time", "请选择时间范围")

确保筛选后参数

筛选是通过后端接口实现,本文示例参数格式为{page:1,size:10,search:[{key1:value1},{key2:value2},{...}...]},其中search为表格筛选条件(对象数组),它的key对应表格中对应列的key。

同时筛选不止表格组件内实现,表格外也有Input可以对表格进行筛选。
在这里插入图片描述

封装函数,确保search中元素对象的唯一性

  • searchArray:筛选参数(本文中为search)
  • key:搜索的列
  • value:搜索条件
const updateTableFilter = (searchArray, key, value) => {
  const foundIndex = searchArray.findIndex((item) => key in item)
  if (value === null) {
    // 删除对应的对象
    if (foundIndex !== -1) {
      searchArray.splice(foundIndex, 1)
    }
  } else if (foundIndex !== -1) {
    // 更新已存在的对象
    searchArray[foundIndex] = { ...searchArray[foundIndex], [key]: value }
  } else {
    // 添加新的对象
    searchArray.push({ [key]: value })
  }

  return searchArray
}

Table组件的筛选通过onChange触发,filters参数会返回对象,其中包括所有可筛选项的值,如未针对某列筛选,那么对应列的value为null。

在这里插入图片描述

封装函数,对filters进行处理

  • filters:Table组件onChange时的参数filters
  • prevSearch:当前筛选条件
const processFilters = (filters, prevSearch) => {
  let searchArray = [...prevSearch] // 确保不直接修改原数组

  Object.entries(filters).forEach(([key, value]) => {
    let filterValue = value
    if (Array.isArray(value) && value.length > 0) {
      const filterFlag = value[value.length - 1] // 尝试获取自定义筛选的标识
      // 处理自定义筛选
      if (filterFlag === "InputTableFilter") {
        filterValue = value[0] // 去掉标识
      } else if (filterFlag === "DateTableFilter") {
        filterValue = value.slice(0, -1) // 去掉标识
      }
    }

    searchArray = updateTableFilter(searchArray, key, filterValue)
  })

  return searchArray
}

使用时:
表格筛选

const onTableChange = (
  { current, pageSize },
  filters 
) => {
  tableparam = {
  	...tableparam,
    page: current,
    size: pageSize,
    search: processFilters(filters, tableparam.search),
  }
}

表格外部筛选(如输入框)

const onSearch = () => {
  tableparam.search = updateTableFilter(
    tableparam.search,
    "name", // 筛选的key
    iptValue // 输入框的值
  )
  // 刷新表格...
}
如果 AntdTable 组件提供的筛选功能不能满足我们的需求,我们可以通过自定义筛选实现更加灵活的功能。具体步骤如下: 1. 在 `columns` 中设置需要筛选的列的 `filterDropdown` 和 `onFilterDropdownVisibleChange` 属性,如下所示: ```javascript const columns = [ { title: '姓名', dataIndex: 'name', key: 'name', filterDropdown: ({ setSelectedKeys, selectedKeys, confirm, clearFilters }) => ( <div style={{ padding: 8 }}> <Input placeholder="请输入姓名" value={selectedKeys[0]} onChange={e => setSelectedKeys(e.target.value ? [e.target.value] : [])} onPressEnter={() => confirm()} /> <Button type="primary" onClick={() => confirm()} style={{ margin: '0 8px' }}> 筛选 </Button> <Button onClick={() => clearFilters()}>重置</Button> </div> ), onFilterDropdownVisibleChange: visible => { if (visible) { setTimeout(() => this.searchInput.select()); } }, onFilter: (value, record) => record.name.indexOf(value) === 0, }, { title: '年龄', dataIndex: 'age', key: 'age', }, { title: '地址', dataIndex: 'address', key: 'address', }, ]; ``` 在上述代码中,我们通过 `filterDropdown` 属性自定义筛选面板的内容,包括一个输入框、一个筛选按钮和一个重置按钮。在输入框中输入筛选条件,然后点击筛选按钮即可进行筛选。`onFilterDropdownVisibleChange` 属性用于在筛选面板显示时自动聚焦输入框。 2. 在 `Table` 组件中设置 `columns` 和 `dataSource` 属性,如下所示: ```javascript class App extends React.Component { state = { dataSource: [], }; componentDidMount() { // 模拟数据请求 setTimeout(() => { this.setState({ dataSource: [ { key: '1', name: 'John Brown', age: 32, address: 'New York No. 1 Lake Park', }, { key: '2', name: 'Jim Green', age: 42, address: 'London No. 1 Lake Park', }, { key: '3', name: 'Joe Black', age: 32, address: 'Sidney No. 1 Lake Park', }, { key: '4', name: 'Jim Red', age: 32, address: 'London No. 2 Lake Park', }, ], }); }, 1000); } render() { const { dataSource } = this.state; return <Table columns={columns} dataSource={dataSource} />; } } ``` 在上述代码中,我们只设置了 `columns` 和 `dataSource` 属性,没有处理筛选操作,因为筛选操作已经在 `filterDropdown` 中实现了。 注意:自定义筛选的实现方式比较灵活,可以根据具体需求进行适当的调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

田本初

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值