Safwan Parkar
Safwan Parkar

Reputation: 349

How can I add buttons to a table's column, that navigate to specific routes upon onClick()

I'm building a dashboard of sorts as part of a project to learn React and NextJS. I'm stuck on an issue that I have found no solution to online. Any help is appreciated!

So I have a page called 'departments.js', which shows a table like the one in the image below. 1

I get the data to fill in the rows and columns from 2 hardcoded JSON stringa:

const data = [
        { name: "Customer Service", num: '56', dept:'custserv' },
        { name: "Human Resources", num: '21', dept:'hr' },
        { name: "Quality Assurance", num: '13', dept:'qa' },
        { name: "Marketing", num: '30', dept:'mark' },
        { name: "Research and Development", num: '17', dept:'rnd' },
        { name: "Operations", num: '49', dept:'ops' },
        { name: "Sales", num: '37', dept:'sales' },
        { name: "Distribution", num: '26', dept:'dist' },
        { name: "IT", num: '12', dept:'it' },
      ]

const column = [
        { heading: 'Department', value: 'name' },
        { heading: 'No. of Employees', value: 'num' },
        { heading: 'Actions', value: 'dept' },
    ];

The dept field in the JSON string should store the name of the js file for that department.

What I want to achieve is - when the user clicks the View Department button in the marketing row, the app navigates to /mark.js.

I have a separate component for the table:
Table.js

const Table = ({ data, column }) => {
    return (
      <table>
        <thead>
          <tr>
            {column.map((item, index) => <TableHeadItem item={item} />)}
          </tr>
        </thead>
        <tbody>
          {data.map((item, index) => <TableRow item={item} column={column} />)}
        </tbody>
      </table>
    )
}

const TableHeadItem = ({ item }) => <th>{item.heading}</th>
const TableRow = ({ item, column }) => (
    <tr>
    {column.map((columnItem, index) => {

      if(columnItem.value.includes('.')) {
        const itemSplit = columnItem.value.split('.')
        return <td>{item[itemSplit[0]][itemSplit[1]]}</td>
      }

      return <td>{item[`${columnItem.value}`]}</td>
    })}
  </tr>
)

export default Table

Here is how I build the table in the departments.js file:

return(
   <div className={styles.tableCont}>
      <Table data={data} column={column} />  {/* data and column JSONs*/}
   </div>
)

I tried declaring a function to build the button for each row with the dept from the data JSON, but I'm not able to do it. Please advise on how to go about this.

My failed attempt

const viewDeptBtn = (dept) => {
        return (
            <button className={styles.viewDeptBtn} onClick={() => router.push('/'+dept)}>
                View Department
            </button>
        )
    }

const column = [
        { heading: 'Department', value: 'name' },
        { heading: 'No. of Employees', value: 'num' },
        { heading: 'Actions', value: viewDeptBtn('dept') },
    ];

Upvotes: 0

Views: 560

Answers (1)

jme11
jme11

Reputation: 17374

If your data is shaped like this:

const data = [
        { name: "Customer Service", num: '56', dept:'custserv' },
        { name: "Human Resources", num: '21', dept:'hr' },
        { name: "Quality Assurance", num: '13', dept:'qa' },
        { name: "Marketing", num: '30', dept:'mark' },
        { name: "Research and Development", num: '17', dept:'rnd' },
        { name: "Operations", num: '49', dept:'ops' },
        { name: "Sales", num: '37', dept:'sales' },
        { name: "Distribution", num: '26', dept:'dist' },
        { name: "IT", num: '12', dept:'it' },
      ]

Then to produce the table rows you'd just have to do the following:

const Button = ({ dept }) => (
    <button onClick={() => router.push(`/${dept}`)}>View Department</button>
);

const TableRow = ({ item }) => (
    <tr>
        <td>{item.name}</td>
        <td>{item.num}</td>
        <td>
            <Button dept={item.dept} />
        </td>
    </tr>
);

const TableHeadItem = ({ item }) => <th>{item.heading}</th>;

export default function Table({data, column}) {
    return (
        <table>
            <thead>
                <tr>
                    {column.map((item, index) => (
                        <TableHeadItem item={item} key={index} />
                    ))}
                </tr>
            </thead>
            <tbody>
                {data.map((item) => (
                    <TableRow item={item} key={item.num} />
                ))}
            </tbody>
        </table>
    );
}

Upvotes: 1

Related Questions