skip to Main Content

How can I disable sorting when clicking on column title and launch sorting by click on icon only?

import React, { useState } from "react";
import { Table, Input } from "antd";
import type { TableColumnsType, TableProps } from "antd";
import { SearchOutlined } from "@ant-design/icons";

interface DataType {
  key: React.Key;
  name: string;
  chinese: number;
  math: number;
  english: number;
}

const App: React.FC = () => {
  const [valueMath, setValueMath] = useState("");

  const FilterByMathInput = (
    <>
      <Input
        placeholder="Search Math"
        value={valueMath}
        onChange={(e) => {
          const currValue = e.target.value;
          setValueMath(currValue);
        }}
      />
    </>
  );

  const columns: TableColumnsType<DataType> = [
    {
      title: "Name",
      dataIndex: "name",
    },
    {
      title: "Chinese Score",
      dataIndex: "chinese",
      sorter: {
        compare: (a, b) => a.chinese - b.chinese,
        multiple: 3,
      },
    },
    {
      title: FilterByMathInput,
      dataIndex: "math",
      sorter: {
        compare: (a, b) => a.math - b.math,
        multiple: 2,
      },
    },
    {
      title: "English Score",
      dataIndex: "english",
      sorter: {
        compare: (a, b) => a.english - b.english,
        multiple: 1,
      },
    },
  ];

  const data: DataType[] = [
    {
      key: "1",
      name: "John Brown",
      chinese: 98,
      math: 60,
      english: 70,
    },
    {
      key: "2",
      name: "Jim Green",
      chinese: 98,
      math: 66,
      english: 89,
    },
    {
      key: "3",
      name: "Joe Black",
      chinese: 98,
      math: 90,
      english: 70,
    },
    {
      key: "4",
      name: "Jim Red",
      chinese: 88,
      math: 99,
      english: 89,
    },
  ];

  const onChange: TableProps<DataType>["onChange"] = (
    pagination,
    filters,
    sorter,
    extra
  ) => {
    console.log("params", pagination, filters, sorter, extra);
  };

  return (
    <Table<DataType> columns={columns} dataSource={data} onChange={onChange} />
  );
};

export default App;

Try it on codesandbox.io

Here is screenshot

Every time I click on input (1) sorting is performed, but I want sorting to happen only when click on sorting icon (2).

Why am I looking for this feature? I need to add filter functionality to some columns and everything is ready but when you click on input to change your query it sorts table every time.

I tried to find any info about it on official Ant Design website and github pages – no helpful info.

2

Answers


  1. I don’t think you can disable the column sorting from the input interactions, but you can try preventing the click event from propagating from the Input up to the underlying column header button that toggles the sorting.

    Add an onClick handler and call stopPropagation on the click event object.

    Example:

    const FilterByMathInput = (
      <Input
        placeholder="Search Math"
        value={valueMath}
        onClick={(e) => e.stopPropagation()} // <-- don't propagate click up
        onChange={(e) => {
          const currValue = e.target.value;
          setValueMath(currValue);
        }}
      />
    );
    

    AntD appears to have several options for column filtering though, and since it’s generally a UI/UX anti-pattern to render interactive elements, i.e. input, inside other interactive elements, i.e. button, you may want to explore your filtering options. See the docs on filters and sorters for examples.

    Login or Signup to reply.
  2. You can achieve this by using antd table components prop and a little bit vanilla javascript. components prop provides complete control for rendering cell, header, table… When rendering HeaderCell, antd provides onClick function as prop (Use console to see all available props) and you can use that to control sorting. Assign a className to each column sort icon and using onClick of th (HeaderCell), check which element trigger triggers click and based on that you can call onClick prop. Also you can set the position of tooltip to icon only by using showSorterTooltip: { target: 'sorter-icon' }.

    Note: Input has onKeyDown to avoid sorting the column

    Here’s the complete:

    import { Input, Table } from 'antd';
    import type { TableColumnsType, TableProps } from 'antd';
    import type React from 'react';
    import { type ComponentPropsWithoutRef, useState } from 'react';
    
    interface DataType {
        key: React.Key;
        name: string;
        chinese: number;
        math: number;
        english: number;
    }
    
    const sortIconClassName = 'custom-icon';
    
    const HeaderCell = (props: ComponentPropsWithoutRef<'th'>) => {
        return (
            <th
                {...props}
                onClick={(e) => {
                    const currentTarget = e.currentTarget as HTMLElement;
                    const sortIconNode = currentTarget.querySelector(`.${sortIconClassName}`);
                    if (sortIconNode?.contains(e.target as HTMLElement)) {
                        props.onClick?.(e);
                    }
                }}
            />
        );
    };
    
    const components: TableProps['components'] = {
        header: {
            cell: HeaderCell
        }
    };
    
    const App: React.FC = () => {
        const [valueMath, setValueMath] = useState('');
    
        const FilterByMathInput = (
            <>
                <Input
                    placeholder='Search Math'
                    value={valueMath}
                    // Here you can customize the onKeyDown event to just stop the propagation for Tab key only
                    onKeyDown={(e) => e.stopPropagation()}
                    onChange={(e) => {
                        const currValue = e.target.value;
                        setValueMath(currValue);
                    }}
                />
            </>
        );
    
        const columns: TableColumnsType<DataType> = [
            {
                title: 'Name',
                dataIndex: 'name'
            },
            {
                title: 'Chinese Score',
                dataIndex: 'chinese',
                sorter: {
                    compare: (a, b) => a.chinese - b.chinese,
                    multiple: 3
                }
            },
            {
                title: FilterByMathInput,
                dataIndex: 'math',
                showSorterTooltip: { target: 'sorter-icon', className: sortIconClassName },
                sorter: {
                    compare: (a, b) => a.math - b.math,
                    multiple: 2
                }
            },
            {
                title: 'English Score',
                dataIndex: 'english',
                sorter: {
                    compare: (a, b) => a.english - b.english,
                    multiple: 1
                }
            }
        ];
    
        const data: Array<DataType> = [
            { key: '1', name: 'John Brown', chinese: 98, math: 60, english: 70 },
            { key: '2', name: 'Jim Green', chinese: 98, math: 66, english: 89 },
            { key: '3', name: 'Joe Black', chinese: 98, math: 90, english: 70 },
            { key: '4', name: 'Jim Red', chinese: 88, math: 99, english: 89 }
        ];
    
        const onChange: TableProps<DataType>['onChange'] = (pagination, filters, sorter, extra) => {
            console.log('params', pagination, filters, sorter, extra);
        };
    
        return <Table<DataType> columns={columns} dataSource={data} onChange={onChange} components={components} />;
    };
    
    export default App;
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search