Custom Pagination
The built-in pagination shows Previous/Next buttons and a "Showing X to Y results" summary. With full pagination (->paginate()), First/Last buttons and the total count are included. You can replace the pagination controls, the empty state, or both.
Custom Pagination UI
Replace the default pagination controls with your own UI using renderPagination (React) or the #pagination slot (Vue). This is useful when integrating with a design system or when you need a different layout - numbered page buttons, infinite scroll triggers, or a "load more" pattern.
<InertiaTable
tableData={servers}
renderPagination={({ links, meta, onPageChange, isFetching }) => (
<div className="flex items-center justify-between px-4 py-4 border-t">
<span className="text-sm text-gray-500">
Showing {meta.from} to {meta.to}
{meta.total != null && <> of {meta.total} results</>}
</span>
<div className="flex gap-2">
<button
disabled={!links.prev || isFetching}
onClick={() => onPageChange(meta.current_page - 1)}
className="px-3 py-1.5 border rounded disabled:opacity-50"
>
Previous
</button>
<button
disabled={!links.next || isFetching}
onClick={() => onPageChange(meta.current_page + 1)}
className="px-3 py-1.5 border rounded disabled:opacity-50"
>
Next
</button>
</div>
</div>
)}
/><InertiaTable :table-data="servers">
<template #pagination="{ links, meta, onPageChange, isFetching }">
<div class="flex items-center justify-between px-4 py-4 border-t">
<span class="text-sm text-gray-500">
Showing {{ meta.from }} to {{ meta.to }}
<template v-if="meta.total != null"> of {{ meta.total }} results</template>
</span>
<div class="flex gap-2">
<button
:disabled="!links.prev || isFetching"
@click="onPageChange(meta.current_page - 1)"
class="px-3 py-1.5 border rounded disabled:opacity-50"
>
Previous
</button>
<button
:disabled="!links.next || isFetching"
@click="onPageChange(meta.current_page + 1)"
class="px-3 py-1.5 border rounded disabled:opacity-50"
>
Next
</button>
</div>
</div>
</template>
</InertiaTable>The render prop (React) or scoped slot (Vue) receives:
interface PaginationRenderProps {
links: PaginationLinks; // { first, last, prev, next } URLs
meta: PaginationMeta; // { current_page, from, to, per_page, total?, last_page? }
onPageChange: (page: number) => void; // navigate to a page number
isFetching: boolean; // true while a navigation is in progress
}links.first and links.last are only present when using ->paginate() (full pagination). With ->simplePaginate(), only prev and next are available. See Pagination for the difference between the two methods.
Custom Empty State
When the table has no rows, a default "No results found." message is shown. For a simple text change, use the emptyText prop. For a fully custom layout with actions or illustrations, use renderEmpty (React) or the #empty slot (Vue).
{/* Simple text override */}
<InertiaTable tableData={servers} emptyText="No servers found" />
{/* Fully custom empty state */}
<InertiaTable
tableData={servers}
renderEmpty={() => (
<div className="p-12 text-center">
<h3 className="text-lg font-medium">No servers yet</h3>
<p className="mt-1 text-gray-500">Create your first server to get started.</p>
<button className="mt-4 px-4 py-2 bg-blue-600 text-white rounded-md">
Create Server
</button>
</div>
)}
/><!-- Simple text override -->
<InertiaTable :table-data="servers" empty-text="No servers found" />
<!-- Fully custom empty state -->
<InertiaTable :table-data="servers">
<template #empty>
<div class="p-12 text-center">
<h3 class="text-lg font-medium">No servers yet</h3>
<p class="mt-1 text-gray-500">Create your first server to get started.</p>
<button class="mt-4 px-4 py-2 bg-blue-600 text-white rounded-md">
Create Server
</button>
</div>
</template>
</InertiaTable>Summary
| Prop | What it does |
|---|---|
renderPagination (React) / #pagination slot (Vue) | Replaces the pagination controls |
emptyText | Changes the empty state message text |
renderEmpty (React) / #empty slot (Vue) | Replaces the entire empty state with custom markup |