antd里面的Table组件,dataSource如果涉及children无法筛选里面的数据?

排序的话,实现起来挺简单,直接在sorter方法里面判断就行,发现筛选onFilter方法里面判断行不通,办法是有,我感觉很复杂,需要跟Table里面的onchange配合使用,得写一堆逻辑,还容易出问题,请问有其它更简单方法实现吗?比如直接在onFilter方法里面实现就行的

onFilter方法是一个布尔值,如果在children里面判断发现行不通
比如:

onFilter: (value, record) => {
 if(record.children){
   //xxx
 }
}

demo

const { createRoot } = ReactDOM;
const {  Space, Switch, Table  } = antd;
const {  useState  } = React;;
const columns = [
  {
    title: 'Name',
    dataIndex: 'name',
    key: 'name',
    filters: [
      {
        text: 'test01',
        value: 'test01',
      },{
        text: 'test02',
        value: 'test02',
      },
      {
        text: 'test10',
        value: 'test10',
      },{
        text: 'test21',
        value: 'test21',
      },
    ],
    onFilter: (value: string, record) => record.name === value
  },
  {
    title: 'Age',
    dataIndex: 'age',
    key: 'age',
    width: '12%',
  },
  {
    title: 'Address',
    dataIndex: 'address',
    width: '30%',
    key: 'address',
  },
];
const data = [
  {
    key: 1,
    name: '测试A',
    age: 60,
    address: 'New York No. 1 Lake Park',
    children: [
      {
        key: 11,
        name: 'test02',
        age: 42,
        address: 'New York No. 2 Lake Park',
      },{
        key: 12,
        name: 'test01',
        age: 22,
        address: 'New York No. 2 Lake Park',
      },
    ],
  },
  {
    key: 2,
    name: '测试A_1',
    age: 29,
    address: 'Sidney No. 1 Lake Park',
  },
  {
    key: 3,
    name: '测试B',
    age: 32,
    address: 'Sidney No. 1 Lake Park',
    children: [
      {
        key: 13,
        name: 'test21',
        age: 25,
        address: 'New York No. 2 Lake Park',
      },{
        key: 14,
        name: 'test01',
        age: 19,
        address: 'New York No. 2 Lake Park',
      },{
        key: 15,
        name: 'test10',
        age: 19,
        address: 'New York No. 2 Lake Park',
      },
    ],
  },{
    key: 4,
    name: '测试B_1',
    age: 29,
    address: 'Sidney No. 1 Lake Park',
  },
];
const App = () => {
  return (
      <Table
        columns={columns}
        dataSource={data}
      />
  );
};
const ComponentDemo = App;


createRoot(mountNode).render(<ComponentDemo />);
阅读 1.4k
avatarAI BotBETA

这个问题确实很常见,antd的Table组件在处理嵌套数据时,特别是当数据结构复杂时,筛选功能可能会变得非常复杂。

在你的例子中,你希望在"onFilter"方法中直接进行筛选,但这个方法只接受两个参数:value 和 record。其中,value 是用户输入的筛选值,而 record 是当前正在被筛选的记录。

然而,你的数据结构中,你希望筛选的是嵌套在 "children" 字段中的数据,这在 "onFilter" 方法中是访问不到的。因为 "onFilter" 方法并不能访问到 record 的子记录。

为了解决这个问题,你可能需要改变你的数据结构,或者在你的 onFilter 方法中增加一些逻辑来处理嵌套的 children 数据。

一种可能的解决方案是,你可以在返回你的数据源时,对 children 数据进行预处理,把每个 child 对象中需要被筛选的字段提取出来,放入一个新的数组中。然后,你可以在 onFilter 方法中直接对这个新的数组进行筛选。这样,你就可以直接在 onFilter 方法中处理嵌套的 children 数据了。

另外一种可能的解决方案是,你可以使用自定义的 Filter 组件来处理 children 数据的筛选。这样,你就可以在 Filter 组件中获取到所有的 record,包括他们的 children 数据,然后你可以在 Filter 组件中实现你自己的筛选逻辑。

注意:这两种解决方案都需要你对数据进行预处理或者自定义组件,可能会增加一些代码的复杂性。但是,这是解决这个问题的一种可能的方式。

3 个回答

你都用 dataSource 了,我理解只要你修改了 dataSource 就没有问题了。

那无非就是从深度优先,递归过滤了

onFilter 的返回值类型是 boolean
image.png

因此你需要修改为

onFilter: (value, record) => {
 if(record.children){
   return record.children.some(item=>item.name.indexOf(value) === 0);
 }
 return false
}

看了下 antd 源码,并没做递归处理,不过每层 children 都是做过浅拷贝的,可以在 onFilter 里面直接对 record.children 进行过滤

image.png

我提了个PR修复了这个问题,下周等 antd 发布了 patch 版本,更新一下就可以了
https://github.com/ant-design/ant-design/pull/47170

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Microsoft
子站问答
访问
宣传栏