reactjsantd

Dynamic antd table title - React


I am using Antd table here, I successfully populated one of the title vertically and I want to populate the other one horizontally, refer to the images for clarification.

Here is my table column:

const columns = [
  {
    title: 'Days',
    dataIndex: 'date',
    defaultSorter: 'ascend',
    key: 'title',
    sorter: (a, b) => a.date.localeCompare(b.date),
    sortDirections: ['descend', 'ascend'],

    render: (date) => getDayName(new Date(date)),
  },
  {
    title: 'period',
    dataIndex: 'period',
  },
}

Datasource or data from api:

  const [data, setData] = useState([]);
  const [loading, setLoading] = useState(false);
  const [query, setQuery] = useState('');

  const fetchData = async () => {
    setLoading(true);
    const { data } = await getTimetable();
    setData(data);
    setLoading(false);
  };
  useEffect(() => {
    fetchData();
  }, []);

Rendering table data:

  <TableContainer columns={columns} rowKey={(record) => record.login.uuid} dataSource={data} />

What I want to achieve:

populate periods horizontally like

What I have right now:

i want to align the titles horizontally


Solution

  • In antd Table, columns need to passed as below format.

    const columns = [
    {
     title: 'Name',
     dataIndex: 'name',
     key: 'name',
    },
    // .... rest of the cols
    ];
    

    So to create dynamic columns from the response data you get here, 1st you need to create the array of objects (cols) as the above format that need to pass for <Table columns={formattedColsfromResponseData}.

    So in your case you need to create columns[] like below format.

    let cols = [
    {
        title: "Days",
        dataIndex: "date",
        defaultSorter: "ascend",
        key: "title",
        sorter: (a, b) => a.date.localeCompare(b.date),
        sortDirections: ["descend", "ascend"]
        render: (date) => getDayName(new Date(date)),
      },
    {
        title: "period 1"
        key: "period 1"
        render: (row) => row.section + " - " + row.subject; // render function for customized data. 
    },
    {
        title: "period 2"
        key: "period 2"
        render: (row) => row.section + " - " + row.subject; // render function for customized data
    },
    // .... rest of the 'Period n' cols in the response.
    ];
    

    With the below method you can create cols as required format by passing the response data.

    This method works assuming response data has only unique 'Periods'.

    const generateColumns = (data) => {
      let cols = [];
      const days = {
        title: "Days",
        dataIndex: "date",
        defaultSorter: "ascend",
        key: "title",
        sorter: (a, b) => a.date.localeCompare(b.date),
        sortDirections: ["descend", "ascend"]
        render: (date) => getDayName(new Date(date)),
      };
      cols.push(days); // add 'Days' obj to Columns.
      
      // for render: property in cols need to return a function. Here creates that.
      const generateRender = (row) => {
        console.log("gen row----", row);
        return (row) => row.section + " - " + row.subject;
      };
    
      // create the col objects for each 'Period'. This method works assuming response data has only unique 'Periods'.
      data.map((row) => {
    
        let period = {}; // for create 'Period' obj for cols.
        period["title"] = row.period;
        period["key"] = row.period;
        period["render"] = generateRender(row); // only need this if you render customized data.
        cols.push(period); // add Current Period obj to Columns.
      });
    
      return cols;
    };
    

    Now you can pass this method to columns prop in Table with response data which returns the dynamic cols.

    const App = () => (
      <div>
        <Table columns={generateColumns(data)} dataSource={data} />
      </div>
    );
    

    Check this full demo antd-dynamic-cols-example code.