sadmann7 / shadcn-table Goto Github PK
View Code? Open in Web Editor NEWA shadcn table component with server-side sorting, filtering, and pagination.
Home Page: https://table.sadmn.com
License: MIT License
A shadcn table component with server-side sorting, filtering, and pagination.
Home Page: https://table.sadmn.com
License: MIT License
Would love to see grouping support: https://tanstack.com/table/latest/docs/guide/grouping
No response
I just checked out AG Grid and it looks cool.
What if we could develop this DataTable into a Batteries Included Table which can be used by the most junior developer to the largest teams.
What other features can be implemented ?
I was thinking of some more features
Sorely missing at the moment. Would love an example for how to implement it.
This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.
These updates have all been created already. Click a checkbox below to force a retry/rebase of any.
These are blocked by an existing closed PR and will not be recreated unless you click a checkbox below.
.github/workflows/code-check.yml
actions/checkout v4
actions/setup-node v4
pnpm/action-setup v3.0.0
actions/cache v4
actions/checkout v4
actions/setup-node v4
pnpm/action-setup v3.0.0
actions/cache v4
actions/checkout v4
actions/setup-node v4
pnpm/action-setup v3.0.0
actions/cache v4
package.json
@hookform/resolvers ^3.3.4
@radix-ui/react-checkbox ^1.0.4
@radix-ui/react-dialog ^1.0.5
@radix-ui/react-dropdown-menu ^2.0.6
@radix-ui/react-icons ^1.3.0
@radix-ui/react-label ^2.0.2
@radix-ui/react-popover ^1.0.7
@radix-ui/react-select ^2.0.0
@radix-ui/react-separator ^1.0.3
@radix-ui/react-slot ^1.0.2
@radix-ui/react-toggle ^1.0.3
@radix-ui/react-toggle-group ^1.0.4
@radix-ui/react-tooltip ^1.0.7
@t3-oss/env-nextjs ^0.10.1
@tanstack/react-table ^8.16.0
class-variance-authority ^0.7.0
clsx ^2.1.1
cmdk ^1.0.0
date-fns ^3.6.0
drizzle-orm ^0.30.10
geist ^1.3.0
nanoid ^5.0.7
next 14.3.0-canary.63
next-themes ^0.3.0
postgres ^3.4.4
react 18.3.1
react-day-picker ^8.10.1
react-dom 18.3.1
react-hook-form ^7.51.4
server-only ^0.0.1
sonner ^1.4.41
tailwind-merge ^2.3.0
tailwindcss-animate ^1.0.7
zod ^3.23.8
@faker-js/faker ^8.4.1
@ianvs/prettier-plugin-sort-imports ^4.2.1
@total-typescript/ts-reset ^0.5.1
@types/eslint ^8.56.10
@types/node ^20.12.11
@types/react ^18.3.2
@types/react-dom ^18.3.0
@typescript-eslint/eslint-plugin ^7.8.0
@typescript-eslint/parser ^7.8.0
autoprefixer ^10.4.19
dotenv-cli ^7.4.2
drizzle-kit ^0.21.1
eslint ^8.57.0
eslint-config-next ^14.2.3
eslint-config-prettier ^9.1.0
eslint-plugin-tailwindcss ^3.15.1
pg ^8.11.5
postcss ^8.4.38
prettier ^3.2.5
prettier-plugin-tailwindcss ^0.5.14
rimraf ^5.0.6
tailwindcss ^3.4.3
tsx ^4.10.0
typescript ^5.4.5
pnpm 8.15.8
https://www.loom.com/share/b92de30f533e4b2bbdf3008811f566ea?sid=5d2f66f4-76bb-45a6-b389-388c2c1688ac
https://table.sadmn.com/?page=1&sort=createdAt.desc&from=2024-05-08&to=2024-05-14
No response
Hello @sadmann7,
The useDataTable is currently always adding "createdAt.desc" to the URL, as it is the default sort in the use-data-table schema constant.
This is an issue, as we might need "updatedAt" or another type of time sorting, or even no time sorting at all, like sorting simply by IDs.
It seems to me that we should make the schema a mandatory parameter for the use-data-table, so users can choose whether to default to "createdAt", somthing else or nothing at all (thus using the ID as it is the default in queries.ts).
Kind regards.
No response
Hi,
requesting a sticky header feature where the scrolling only happens within the tbody
Hi, thank you very much for creating this wonderful component.. This is really helpful.
One issue i have though while using it was that the page parameter resets back to page=1
if I reload the browser while I'm in a different page (ex. page=3
).
It also reset back to page=1 if I directly visit a url with parameter (ex. page=2, page=3, etc. )
The values in the update sheet were not the values of the selected item after create a new item
Reproduce in the demo site: https://table.sadmn.com/
Hi all, i clone your repo and run in my local. I use mysql/mysql-server:8 and node v20.9.0. When i access to path "/", i get an exception:
⨯ Internal error: TypeError: fetch failed at Object.fetch (node:internal/deps/undici/undici:11372:11) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) Cause: [Error: 00683F3B8E7F0000:error:0A00010B:SSL routines:ssl3_get_record:wrong version number:../deps/openssl/openssl/ssl/record/ssl3_record.c:354: ] { library: 'SSL routines', reason: 'wrong version number', code: 'ERR_SSL_WRONG_VERSION_NUMBER' } ⨯ Internal error: TypeError: fetch failed at Object.fetch (node:internal/deps/undici/undici:11372:11) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) digest: "3747308182"
Anyone could help me? Thanks so much!
Example click on this link.
https://shadcn-table-alt.vercel.app/?page=1&status=in-progress&priority=medium
We should have status set to "in progress" and priority set to "medium".
Instead of this, everything is reset.
If I select the first item in the list, when I move to the next page the first item is still selected. I've fixed this in useDataTable in our project by simply adding this
Not sure if this is a good approach (notably if I increase the per-page this won't persist already selected items), and I've notice it still happens when I select filters.
Date range in UI isn't persisted across reloads
No response
Not sure if missing something but https://table.sadmn.com/ is showing a 404 message
Go to https://table.sadmn.com/
No response
Could you add a boolean filter ?
Many thanks in advance :)
Actually we can filter by search text, by selectable options, there is no simple boolean filter.
No results returned.
Turn on advance filtering
Filter by something
https://table.sadmn.com/?page=1&sort=createdAt.desc&per_page=10&operator=and&title=We.contains
Note that the link generated by the advanced filtering case does not initialize the table state appropriately in an advanced state, too.
I'd like to have as many rows in the table as possible to fill the container/viewport on load (i.e. no need on resize). At the moment it is set by a select dropdown.
Additional details here...
Hi. what params in the useDataTable
to set to have a full page without pagination?
pageCount: -1
or pageCount: 1
doesn't work?
I noticed in the demo when you select a filter and also use the Title search/filter, once you click on reset; the filter value is not fully reset and still is preset in the URL. Here's a quick screencast top to show you what I am running into.
By the way, thank you so much @kavinvalli & @sadmann7 for creating this. I found it while watching your livecode247 channel on youtube. It has been very helpful and exactly what I have been looking for. 🙏🏻
Add the ability to export data to csv
Additional details here...
Hello! First of all great contribution to OSS on how to use shadcn with server side pagination, not an easy task.
I was testing the implementation and it seems that when setting different page size from initial (p.e.: 20) is not working?
Thanks a lot
EDIT: I've been testing a little bit more and I found that if you set it on the URL it works, but when changing on the popover don't. Also I have checked that, for example if you are on the second page and then you change the page size from 20 to 10, it does not reload and instead it goes to the 3rd page.
shadcn already has a toast component. So why do we use sonner? Seems to be adding an extra dependency
I have a table with userId
field, but it is not helpful to display it as is, instead It would be nice to have the ability to easily add columns from the referenced table (user.name
):
export const users = pgTable("users", {
id: serial("id").primaryKey(),
createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at").default(sql`current_timestamp`),
})
export const tasks = pgTable("tasks", {
id: varchar("id", { length: 30 })
.$defaultFn(() => generateId())
.primaryKey(),
// ...
userId: integer("user_id").notNull().references(() => users.id),
createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at").default(sql`current_timestamp`),
})
export const tasksRelations = relations(tasks, ({ one }) => ({
user: one(users, {
fields: [tasks.userId],
references: [users.id],
}),
}));
p.s. I've tried it myself, it did work, but it's very hacky and also type for DataTableFilterField.value
had to be changed to string, because the id of my column was user_name
as a result of referencing
Also, maybe we can utilize dynamic query building for better types and more reusability:
https://orm.drizzle.team/docs/dynamic-query-building
If inside the xxx-table-column we add enableSorting:true and enableHiding:false to a column definition, the column header keep showing hide option in the dropdown menu.
We can do the following to reflect enableHide:false :
{column.getCanHide() ? (
<>
<DropdownMenuSeparator />
<DropdownMenuItem
aria-label="Hide column"
onClick={() => column.toggleVisibility(false)}
>
<EyeNoneIcon
className="mr-2 size-3.5 text-muted-foreground/70"
aria-hidden="true"
/>
Hide
</DropdownMenuItem>
</>
) : null}
also :
If enableHiding: true but enableSorting:false we loose the sorting dropdown containing the quick access to the hide option.
I propose the following :
if (!column.getCanSort() && !column.getCanHide()) {
return <div className={cn(className)}>{title}</div>
}
return (
<div className={cn("flex items-center space-x-2", className)}>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
aria-label={
column.getCanSort()
? column.getIsSorted() === "desc"
? `Sorted descending. Click to sort ascending.`
: column.getIsSorted() === "asc"
? `Sorted ascending. Click to sort descending.`
: `Not sorted. Click to sort ascending.`
: undefined
}
variant="ghost"
size="sm"
className="-ml-3 h-8 data-[state=open]:bg-accent"
>
<span>{title}</span>
{column.getCanSort() ? (
column.getIsSorted() === "desc" ? (
<RxArrowDown className="ml-2 size-4" aria-hidden="true" />
) : column.getIsSorted() === "asc" ? (
<RxArrowUp className="ml-2 size-4" aria-hidden="true" />
) : (
<RxCaretSort className="ml-2 size-4" aria-hidden="true" />
)
) : (
<RxCaretSort className="ml-2 size-4" aria-hidden="true" />
)}
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="start">
{column.getCanSort() ? (
<>
<DropdownMenuItem
aria-label="Sort ascending"
onClick={() => column.toggleSorting(false)}
>
<ArrowUpIcon
className="mr-2 size-3.5 text-muted-foreground/70"
aria-hidden="true"
/>
Asc
</DropdownMenuItem>
<DropdownMenuItem
aria-label="Sort descending"
onClick={() => column.toggleSorting(true)}
>
<ArrowDownIcon
className="mr-2 size-3.5 text-muted-foreground/70"
aria-hidden="true"
/>
Desc
</DropdownMenuItem>
</>
) : null}
{column.getCanSort() && column.getCanHide() ? (
<DropdownMenuSeparator />
) : null}
{column.getCanHide() ? (
<DropdownMenuItem
aria-label="Hide column"
onClick={() => column.toggleVisibility(false)}
>
<EyeNoneIcon
className="mr-2 size-3.5 text-muted-foreground/70"
aria-hidden="true"
/>
Hide
</DropdownMenuItem>
) : null}
</DropdownMenuContent>
</DropdownMenu>
</div>
)
Note : we should maybe also add a clearSorting that would go back to the initial sorting ? this one I m not sure if it is necessary.
add enableSorting: true and enableHiding: false to a column def
No response
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.