Build Dynamic Tables in Minutes!

Simplify your workflow with our Next.js table-building tool powered by the ShadCN design library. Quickly scaffold essential features like search, pagination, sorting, create, edit, and delete. With seamless integration of ShadCN Form Builder , you can customize forms effortlessly and have a fully functional table ready in no time.

Whether you're a beginner or an experienced developer, our tool accelerates development while keeping it flexible and intuitive. Get started today and transform the way you build tables!

pagination
sorting
create
edit
delete
multiDelete
search

Table Preview

Name
Age
Gender
Email
Jane Doe30femalejane@test.com
Alice Smith28femalealice@test.com
Bob Johnson35malebob@test.com
Charlie Brown22malecharlie@test.com
Diana Prince29femalediana@test.com
components
form.tsx
data-table.tsx
column.tsx
types
table.ts
1

Copy and paste the form code from ShadCN-Form-Builder into your project.

The code will be look like this initially.

form.tsx
"use client"
import {
  useState
} from "react"
import {
  toast
} from "sonner"
import {
  useForm
} from "react-hook-form"
import {
  zodResolver
} from "@hookform/resolvers/zod"
import * as z from "zod"
import {
  cn
} from "@/lib/utils"
import {
  Button
} from "@/components/ui/button"
import {
  Form,
  FormControl,
  FormDescription,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
} from "@/components/ui/form"
import {
  Input
} from "@/components/ui/input"
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue
} from "@/components/ui/select"

const formSchema = z.object({
  name_4603829743: z.string(),
  name_0878515932: z.number(),
  name_0706064476: z.string().optional(),
  name_6646786819: z.string()
});

export default function MyForm() {

  const form = useForm < z.infer < typeof formSchema >> ({
    resolver: zodResolver(formSchema),

  })

  function onSubmit(values: z.infer < typeof formSchema > ) {
    try {
      console.log(values);
      toast(
        <pre className="mt-2 w-[340px] rounded-md bg-slate-950 p-4">
          <code className="text-white">{JSON.stringify(values, null, 2)}</code>
        </pre>
      );
    } catch (error) {
      console.error("Form submission error", error);
      toast.error("Failed to submit the form. Please try again.");
    }
  }

  return (
    <Form {...form}>
      <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8 max-w-3xl mx-auto py-10">
        
        <div className="grid grid-cols-12 gap-4">
          
          <div className="col-span-6">
            
        <FormField
          control={form.control}
          name="name_4603829743"
          render={({ field }) => (
            <FormItem>
              <FormLabel>Name</FormLabel>
              <FormControl>
                <Input 
                placeholder="shadcn"
                
                type="text"
                {...field} />
              </FormControl>
              <FormDescription>This is your public display name.</FormDescription>
              <FormMessage />
            </FormItem>
          )}
        />
          </div>
          
          <div className="col-span-6">
            
        <FormField
          control={form.control}
          name="name_0878515932"
          render={({ field }) => (
            <FormItem>
              <FormLabel>Age</FormLabel>
              <FormControl>
                <Input 
                placeholder="shadcn"
                
                type="number"
                {...field} />
              </FormControl>
              <FormDescription>This is your public display name.</FormDescription>
              <FormMessage />
            </FormItem>
          )}
        />
          </div>
          
        </div>
        
        <div className="grid grid-cols-12 gap-4">
          
          <div className="col-span-6">
            
        <FormField
          control={form.control}
          name="name_0706064476"
          render={({ field }) => (
            <FormItem>
              <FormLabel>Gender</FormLabel>
              <Select onValueChange={field.onChange} defaultValue={field.value}>
                <FormControl>
                  <SelectTrigger>
                    <SelectValue placeholder="Select a verified email to display" />
                  </SelectTrigger>
                </FormControl>
                <SelectContent>
                  <SelectItem value="m@example.com">m@example.com</SelectItem>
                  <SelectItem value="m@google.com">m@google.com</SelectItem>
                  <SelectItem value="m@support.com">m@support.com</SelectItem>
                </SelectContent>
              </Select>
                <FormDescription>You can manage email addresses in your email settings.</FormDescription>
              <FormMessage />
            </FormItem>
          )}
        />
          </div>
          
          <div className="col-span-6">
            
        <FormField
          control={form.control}
          name="name_6646786819"
          render={({ field }) => (
            <FormItem>
              <FormLabel>Email</FormLabel>
              <FormControl>
                <Input 
                placeholder="shadcn"
                
                type="email"
                {...field} />
              </FormControl>
              <FormDescription>This is your public display name.</FormDescription>
              <FormMessage />
            </FormItem>
          )}
        />
          </div>
          
        </div>
        <Button type="submit">Submit</Button>
      </form>
    </Form>
  )
}
2

Align Import Paths with Project Structure and Update `form.tsx`

Ensure that the import paths align with your project's directory structure and naming conventions. Additionally, verify that all required packages are installed. Once these steps are completed, proceed to update the `form.tsx` file as outlined below.

form.tsx

    // Update import paths
    import { MyFormData } from "@types/table";
    ...

    // update formSchema as per requirement add id as optional
    const formSchema = z.object({
      id: z.string().optional(),
      name_4603829743: z.string().min(2, { message: "Name must be at least 2 characters" }),
      name_0878515932: z.coerce.number().min(0, { message: "Age must be a positive number" }),
      name_0706064476: z.string().optional(),
      name_6646786819: z.string().email({ message: "Invalid email address" }),
    });

    // Add an interface for user form props
    interface MyFormProps {
      onSubmit: (data: MyFormData) => void;
      initialData?: MyFormData | null;
    }

    // Define the MyForm component with enhanced functionality
    export function MyForm({ onSubmit, initialData }: MyFormProps) {
    ...

    // Set default values for the form
    const form = useForm<z.infer<typeof formSchema>>({
        resolver: zodResolver(formSchema),
        defaultValues: initialData || {
        name_4603829743: "",
        name_0878515932: 0,
        name_0706064476: "",
        name_6646786819: "",
      },
    })

    //Add onSubmit on HandleSubmit function
    function handleSubmit(values: z.infer<typeof formSchema>) {
        try {
        onSubmit(values as MyFormData)
        form.reset()
        toast.success("User data submitted successfully!")
        } catch (error) {
        console.error("Form submission error", error)
        toast.error("Failed to submit the form. Please try again.")
        }
    }

    // update onsubmit in form
    return (
      <Form {...form}>
        <form
          onSubmit={form.handleSubmit(handleSubmit)}
          className="space-y-8 ...

    // Include a dynamic button for creating or updating user data
    <Button type="submit">{initialData ? "Update" : "Create"}</Button>
    
3

Define a TypeScript Interface for Form Data

Create a TypeScript interface to define the structure of form data, specifying field names and their respective data types for better type safety and maintainability.

table.ts
export interface MyFormData {
  id: string;
  name_4603829743: string;
  name_0878515932: number;
  name_0706064476: string;
  name_6646786819: string;
}
4

Create a Column Component with React Table

Implement a column component using `@tanstack/react-table` to display and manage structured data. Leverage the `MyFormData` type to define column configurations, ensuring clarity and type safety.

column.tsx
"use client";

import { ColumnDef } from "@tanstack/react-table";
import { MyFormData } from "./types";


  export const createColumns = (): ColumnDef<MyFormData>[] => {
    const columns: ColumnDef<MyFormData>[] = [
      {
      accessorKey: "name_4603829743",
      header: "Name",
      },
      {
        accessorKey: "name_0878515932",
        header: "Age",
      },
      {
        accessorKey: "name_0706064476",
        header: "Gender",
      },
      {
        accessorKey: "name_6646786819",
        header: "Email",
      },
    ];


    return columns;
  };
5

Build a Data Table Component

Develop a data-table component to display structured data effectively. Integrate column definitions and data handling to create an interactive and user-friendly table.

data-table.tsx
"use client";

import { useState } from "react";
import {
  ColumnDef,
  flexRender,
  ColumnFiltersState,
  getCoreRowModel,
  getFilteredRowModel,
  getPaginationRowModel,
  useReactTable,
  SortingState,
  getSortedRowModel,
} from "@tanstack/react-table";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";

interface DataTableProps<TData, TValue> {
  columns: ColumnDef<TData, TValue>[];
  data: TData[];
}

export function DataTable<TData, TValue>({
  columns,
  data,
  
  
  
  
}: DataTableProps<TData, TValue>) {
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);

  const table = useReactTable({
    data,
    columns,
    getCoreRowModel: getCoreRowModel(),
    getPaginationRowModel: getPaginationRowModel(),
    onColumnFiltersChange: setColumnFilters,
    getFilteredRowModel: getFilteredRowModel(),
    state: {
      columnFilters,
    },
  });


  return (
    <div className="space-y-4">
      <div className="flex items-center justify-between">
        
        <Input
          placeholder="Filter..."
          // value={(table.getColumn("name_4603829743")?.getFilterValue() as string) ?? ""}
          // onChange={(event) =>
          //   table.getColumn("name_4603829743")?.setFilterValue(event.target.value)
          // }
          className="max-w-sm"
        />
        <div className="flex items-center gap-4">
          
          
        </div>
      </div>
      <div className="rounded-md border">
        
        <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?.length ? (
              table.getRowModel().rows.map((row) => (
                <TableRow
                  key={row.id}
                  data-state={row.getIsSelected() && "selected"}
                >
                  
                  {row.getVisibleCells().map((cell) => (
                    <TableCell key={cell.id}>
                      {flexRender(
                        cell.column.columnDef.cell,
                        cell.getContext()
                      )}
                    </TableCell>
                  ))}
                </TableRow>
              ))
            ) : (
              <TableRow>
                <TableCell
                  colSpan={columns.length}
                  className="h-24 text-center"
                >
                  No results.
                </TableCell>
              </TableRow>
            )}
          </TableBody>
        </Table>
      </div>
      
      <div className="flex items-center justify-end space-x-2 py-4">
        <Button
          variant="outline"
          size="sm"
          onClick={() => table.previousPage()}
          disabled={!table.getCanPreviousPage()}
        >
          Previous
        </Button>
        <Button
          variant="outline"
          size="sm"
          onClick={() => table.nextPage()}
          disabled={!table.getCanNextPage()}
        >
          Next
        </Button>
      </div>
    </div>
  );
}
6

Develop a Page Component

Implement a page component that combines and renders the form and data-table components to create a cohesive user interface.

page.tsx
"use client";

import { useState } from "react";
import { createColumns } from "./column";
import { DataTable } from "./data-table";
import { MyFormData } from "./types";

const initialData: MyFormData[] = [
   {
    id: "1",
    name_4603829743: "Jane Doe",
    name_0878515932: 30,
    name_0706064476: "female",
    name_6646786819: "jane@test.com",
  },
];

export default function TablePage() {
  const [data, setData] = useState<MyFormData[]>(initialData);
const columns = createColumns();
return (

    <div className="container mx-auto py-10">
      
      <DataTable
        columns={columns}
        data={data}
      />
    </div>
  );
}