In this lesson, we will add pagination to our table. It won't be an easy one-minute process.
Modifying Controller for Pagination
app/Http/Controllers/TaskController.php
// ... public function index(){ return Inertia::render('Tasks/Index', [ 'tasks' => Task::all() 'tasks' => Task::paginate(5) ]);} // ...
Now, our Task List page will stop working because of a TypeScript structure mismatch. We return paginate() from Controller, which is no longer the array of the Task type. Let's fix this.
Creating Paginated Response Type
We return tasks from the Controller not as a list but as a paginated object.
So, we need to create a specific new type for it, corresponding to the structure returned by Laravel pagination.
resources/js/types/index.d.ts
// ... export interface PaginatedResponse<T = Task | null> { current_page: number; data: T[]; first_page_url: string; from: number; last_page: number; last_page_url: string; links: { url: string | null; label: string; active: boolean; }[]; next_page_url: string | null; path: string; per_page: number; prev_page_url: string | null; to: number; total: number;}
Accepting Paginated Response in React
In three places, we need to change the type of data we get.
- We import our new
PaginatedResponsetype - We use it in the
export functioninstead of...
The shadcn pagination component uses a regular
<a>tag for the links, so you'll notice that the pagination links cause a full page refresh. This can be remedied by updating the shadcn component to use the Inertia<Link>component.The great thing about shadcn and the way that the Laravel Starter Kits are implemented is that you can modify the components in this way, so no messy extending. Just be careful not to overwrite the changes later!
Thanks for the valuable comment, Joe, great notice!
That's a great point Joe however I just tried to naively update resources/js/components/ui/pagination.tsx to use "Link" instead of "a" and got myself into all sorts of trouble. Anyone got some hints or a Gist?
Yeah, it's pretty easy to break. I ended up enlisting the help of AI to do it. Here's what we came up with...
First import the inertia
<Link>at the top:Then redefine the
PaginationLinkPropstype slightly:Finally replace the
PaginationLinkfunction with this:Just an observation, after the custom
table-pagination.tsxcomponent is created, the step where the component is used is missing. This can be confusing to readers who are just following along. The following needs to be added to theTasks/Index.tsxfor the pagination to show;Wow, how could I miss this... fixed now! Thanks Steve for being a proofreader! Need to spend more time on double-checking everything in the future. Perhaps too much in a hurry to release everything related to Laravel 12, when people are asking so many question.
No worries my friend, happy to help! Hope to see you at Laravel Live London :)
I get error in console log. And I fixed it in resources/js/lib/generate-pagination-links.tsx by adding 2 keys to
PaginationEllipsiskey="ellipsis-before" and key="ellipsis-after"For the
PaginatedResponseinterface to be generally useful you need to remove the default typeTaskand leave the generic declaration without any default type. It makes no sense to have an arbitrary dependency onTask. You can close the type declaration where it's used by specifying the type at that point.For example, the table pagination component would become an open generic function:
export function TablePagination<T>({resource}: {resource: PaginatedResponse<T>})...You then close the function when it's used in the TSX markup, for example if you're paginating a list of Task, like this:
<TablePagination<Task> resource={tasks} />You also have to remove the dependency on
TaskfromTablePaginationand fromgeneratePaginationLinks, making them also generic on T.After doing that, you have pagination components that can be used in any project without having to edit the code and change the dependency on
Taskto something else.Thank you for this! It's something we might have lacked knowledge on in typescript as I did not get it working correctly.
Will most likely update the article with your suggestion :)
I think it would be most useful to add a chapter with data-table. https://ui.shadcn.com/docs/components/data-table
We will chat internally to see if we should add it, but it will require a lot more work as there's more to DataTables than what we have right now
It surely is but that would be the real life case. If I may suggest something - it should be kind of drop-in replacement for datatables you have in the Quick Panel which I always was big fan of. Thank you for considering it anyway.
Yeah, so this is exactly what I had in mind when I said that it's complicated :)
The Quickadmin DataTables are complex and offer a lot of functionality, which is not easilly replicatable (thanks to a great package we used then!). To make an almost identical copy - it would take us a lot of time, and then to explain everything and how it works - even more. Maybe it's a good idea to start an open-source project, but for us at this moment it's a no-go, sorry!
ps. Happy to see a happy customer of product we had!
Yes I quite understand. I really liked it and I learned a lot from it. I think your way of doing things and how you explain them is compatible with my mind. Thank you for all your great work.