Published on

How to Build Tables with Dynamic Headers in Shadcn

Authors
  • Name
    Ripal & Zalak
    Twitter

Dynamic Table Headers in Shadcn Data Table

In modern web applications, tables often need to adapt to various datasets with dynamic headers. This guide explains how to create a Shadcn Data Table with variable headers while incorporating fixed-width action columns.

Overview

Dynamic headers make your table flexible for different datasets. With Shadcn's Data Table and Tailwind CSS, you can easily implement this functionality while maintaining responsiveness and usability.

Step-by-Step Implementation

Step 1: Define Variable Headers

To define headers dynamically, create a columns array that adapts based on your dataset.

export function getDynamicColumns(data) {
  const dynamicHeaders = Object.keys(data[0] || {}).map((key) => ({
    accessorKey: key,
    header: key.charAt(0).toUpperCase() + key.slice(1), // Capitalize headers
    cell: ({ row }) => row.original[key],
  }))

  const actionColumn = {
    id: 'actions',
    header: 'Actions',
    cell: ({ row }) => (
      <div className="flex justify-center">
        <button className="rounded-md bg-red-500 px-2 py-1 text-sm text-white">Delete</button>
      </div>
    ),
    enableSorting: false,
    enableHiding: false,
  }

  return [...dynamicHeaders, actionColumn]
}

Step 2: Pass Columns Dynamically

In the parent component, use the getDynamicColumns function to generate columns based on the data.

import { useReactTable } from '@tanstack/react-table'
import { getDynamicColumns } from './columns'
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from 'shadcn/ui/table'

export function DynamicTable({ data }) {
  const columns = getDynamicColumns(data)

  const table = useReactTable({
    data,
    columns,
    getCoreRowModel: getCoreRowModel(),
  })

  return (
    <div className="w-full">
      <Table>
        <TableHeader>
          {table.getHeaderGroups().map((headerGroup) => (
            <TableRow key={headerGroup.id}>
              {headerGroup.headers.map((header) => (
                <TableHead key={header.id}>
                  {header.isPlaceholder
                    ? null
                    : flexRender(header.column.columnDef.header, header.getContext())}
                </TableHead>
              ))}
            </TableRow>
          ))}
        </TableHeader>
        <TableBody>
          {table.getRowModel().rows.map((row) => (
            <TableRow key={row.id}>
              {row.getVisibleCells().map((cell) => (
                <TableCell key={cell.id}>
                  {flexRender(cell.column.columnDef.cell, cell.getContext())}
                </TableCell>
              ))}
            </TableRow>
          ))}
        </TableBody>
      </Table>
    </div>
  )
}

Step 3: Add Fixed-Width Columns

To set a fixed width for action columns, use Tailwind CSS classes in the column definition.

const actionColumn = {
  id: 'actions',
  header: 'Actions',
  cell: ({ row }) => (
    <div className="flex justify-center">
      <button className="rounded-md bg-red-500 px-2 py-1 text-sm text-white">Delete</button>
    </div>
  ),
  size: 100, // Fixed width
  enableSorting: false,
  enableHiding: false,
}

Step 4: Make the Table Responsive

To ensure responsiveness, wrap the table in a scrollable container using Tailwind CSS.

<div className="overflow-x-auto">
  <Table>{/* Table content */}</Table>
</div>

Benefits of Dynamic Headers

  1. Flexibility: Adapt headers to various datasets without hardcoding.
  2. User-Friendly: Maintain a clean and responsive table layout.
  3. Customizable: Add fixed-width columns for consistent action buttons or controls.

FAQs

1. How do I handle datasets with inconsistent keys?

Use a function to normalize the dataset and ensure consistent keys before passing it to the table.

2. Can I customize the styling of headers and cells?

Yes, use Tailwind CSS or custom classes in the header and cell properties.

3. What if my table has too many columns to fit on small screens?

Wrap the table in an overflow-x-auto container and use horizontal scrolling for better usability.

Conclusion

Dynamic headers in a Shadcn Data Table enhance the flexibility and scalability of your application. By using a combination of dynamic column definitions and Tailwind CSS, you can create a responsive, user-friendly table layout tailored to your needs.