Skip to content

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.

tsx
<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>
    )}
/>
template
<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:

tsx
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).

tsx
{/* 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>
    )}
/>
template
<!-- 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 ​

PropWhat it does
renderPagination (React) / #pagination slot (Vue)Replaces the pagination controls
emptyTextChanges the empty state message text
renderEmpty (React) / #empty slot (Vue)Replaces the entire empty state with custom markup