Search code examples
reactjsantddraggablereact-functional-component

How can i use react-drag-listview with functional components to make draggable columns with antd-table?


I'm trying to create a draggable table with antd, but i always use functionalcomponents in react and all the examples and doc that i found in internet is using class components and that=this stufs like. I don't know how can i use react-drag-listview library with the functional components.

this.state = {
  columns: [
    {
      title: <span className="dragHandler">Key</span>,
      dataIndex: "key",
      render: (text) => <span>{text}</span>,
      width: 50
    },
    {
      title: <span className="dragHandler">Name</span>,
      dataIndex: "name",
      width: 200
    },
    {
      title: <span className="dragHandler">Gender</span>,
      dataIndex: "gender",
      width: 100
    },
    {
      title: <span className="dragHandler">Age</span>,
      dataIndex: "age",
      width: 100
    },
    {
      title: <span className="dragHandler">Address</span>,
      dataIndex: "address"
    }
  ]
};

const that = this;
this.dragProps = {
  onDragEnd(fromIndex, toIndex) {
    const columns = [...that.state.columns];
    const item = columns.splice(fromIndex, 1)[0];
    columns.splice(toIndex, 0, item);
    that.setState({
      columns
    });
  },
  nodeSelector: "th",
  handleSelector: ".dragHandler",
  ignoreSelector: "react-resizable-handle"
};

}

This a small piece of code that I'm trying to copy from, but i don't understand it. Even an exaple of any small code where i can see how to use with functional components it may work for me.

Tis is the url of the example above: https://codesandbox.io/s/table-column-sortable-resizable-st9bt?file=/index.js


Solution

  • React Drag List View Using Functional Component

    import "./index.css";
    import { useState } from "react";
    import { Resizable } from "react-resizable";
    import { Table } from "antd";
    import ReactDragListView from "react-drag-listview";
    
    const ResizableTitle = (props) => {
      const { onResize, width, ...restProps } = props;
    
      if (!width) {
        return <th {...restProps} />;
      }
    
      return (
        <Resizable
          width={width}
          height={0}
          handle={
            <span
              className='react-resizable-handle'
              onClick={(e) => {
                e.stopPropagation();
              }}
            />
          }
          onResize={onResize}
          draggableOpts={{ enableUserSelectHack: false }}
        >
          <th {...restProps} />
        </Resizable>
      );
    };
    
    const data = [
      { key: "1", name: "Boran", gender: "male", age: "12", address: "New York" },
      { key: "2", name: "JayChou", gender: "male", age: "38", address: "TaiWan" },
      { key: "3", name: "Lee", gender: "female", age: "22", address: "BeiJing" },
      { key: "4", name: "ChouTan", gender: "male", age: "31", address: "HangZhou" },
      { key: "5", name: "AiTing", gender: "female", age: "22", address: "Xi’An" },
    ];
    
    const components = { header: { cell: ResizableTitle } };
    
    const App = () => {
      const [columns, setColumns] = useState([
        {
          title: <span className='dragHandler'>Key</span>,
          dataIndex: "key",
          render: (text) => <span>{text}</span>,
          width: 50,
        },
        {
          title: <span className='dragHandler'>Name</span>,
          dataIndex: "name",
          width: 200,
        },
        {
          title: <span className='dragHandler'>Gender</span>,
          dataIndex: "gender",
          width: 100,
        },
        {
          title: <span className='dragHandler'>Age</span>,
          dataIndex: "age",
          width: 100,
        },
        {
          title: <span className='dragHandler'>Address</span>,
          dataIndex: "address",
        },
      ]);
    
      const onDragEnd = (fromIndex, toIndex) => {
        setColumns((prev) => {
          const nextColumns = [...prev];
          const item = nextColumns.splice(fromIndex, 1)[0];
          nextColumns.splice(toIndex, 0, item);
          return nextColumns;
        });
      };
    
      const handleResize = (size, index) => {
        setColumns((prev) => {
          const nextColumns = [...prev];
          nextColumns[index] = {
            ...nextColumns[index],
            width: size.width,
          };
          return nextColumns;
        });
      };
    
      const tableColumns = columns.map((col, index) => ({
        ...col,
        onHeaderCell: (column) => ({
          width: column.width,
          onResize: (e, { size }) => handleResize(size, index),
        }),
      }));
    
      return (
        <ReactDragListView.DragColumn
          onDragEnd={onDragEnd}
          nodeSelector='th'
          handleSelector='.dragHandler'
          ignoreSelector='react-resizable-handle'
        >
          <Table bordered columns={tableColumns} dataSource={data} components={components} />
        </ReactDragListView.DragColumn>
      );
    };
    
    export default App;