Ahmed Hosny
Ahmed Hosny

Reputation: 470

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

Upvotes: 0

Views: 3284

Answers (1)

DevThiman
DevThiman

Reputation: 1138

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.

Upvotes: 1

Related Questions