Search code examples
javascripthtmlcssreactjshtml-table

How to synchronize table headers with their content?


I need to ensure that the table columns align with their respective headers. Given an array of headers as follows:

const titles = ['name', 'lastname', 'age']

when rendering the table, the content, which may look as follows:

const content = ['lastnameText', 15, 'nameText']

should adjust to match the corresponding headers.

The challenge here is that the order of items in the content array may not match the order of headers.

<table>
  <thead>
    {titles.map(item => (
      <tr>{item}</tr>
    ))}
  </thead>
  <tbody>
    {content.map(item => (
      <tr>{item}</tr>
    ))}
  </tbody>
</table>

Currently, the result appears as follows:

   name       lastname     age
lastnametext     15      nametext

As you can see, the header columns are not correctly positioned. The desired outcome should look as follows:

   name      lastname     age
 nameText  lastnametext   15

Solution

  • Edited this answer and found a solution for what you want. See this code.

    *Note: If all the rows fields in your content are in matching order, and just the headers order is the problem - then this code is enough.


    So in order to make it work as a re-useable table, and work even if the content order is messed up - what I do is simply sorting the content I get before displaying it:

      const allSortedContent = []; 
    
      for (const row in props.content) {
        const sortedRowValues = []; 
        // Pushing the values of this row to the `sortedValues` according the order of the headers.
        props.headers.forEach((header) => {
          const value = props.content[row][header];
          sortedRowValues.push(<td>{value}</td>);
        });
        allSortedContent.push(<tr>{sortedRowValues}</tr>);
      }
    

    Here I go through the content array which contains rows as objects. For each row - I sort the fields of it to be according the order of the headers. In each iteration, I use the sortedRowValues array that will contain the <td> elements of this row (matching the order of the headers).

    After finishing each row, I push the mapped row - (sortedRowValues) to the allSortedContent array which contains all the sorted rows.

    Lastly, in the table body, I simply return the allSortedContent.

    return (
        <div>
          <table>
            <thead>
              <tr>
                {props.headers.map((item) => (
                  <td>{item}</td>
                ))}
              </tr>
            </thead>
            <tbody>{allSortedContent}</tbody>
          </table>
        </div>
      );
    

    And the data structure you send through props should be in this structure, but it's completely okay if it's out of order:

    const headers = ['age', 'lastName', 'name'];
    
    const content = [
        { name: 'Jule', lastName: 'Abc', age: '24' },
        { lastName: 'Park', age: '32', name: 'Josh' },
      ];