Skip to content

Slots

Inertia Table exposes Vue slots (and equivalent React render props) for every customizable region: the topbar, filters, table body, header, individual cells, footer, and loading overlay. Use them to drop in your own controls or layout fragments without forking the component or going fully headless. Each slot receives the same table and actions scope you'd get from useTable() and useActions().

For a refresher on Vue slots, see the Vue documentation.

Global Slots

The Table component has the following high-level slots:

SlotDescription
loadingThe overlay that is displayed when the table is loading data.
topbarThe entire topbar (search, actions, filters, columns). Replaces the default topbar completely.
beforeSearchInjected before the search input.
afterSearchInjected after the search input.
beforeActionsInjected before the Views/Actions/Filters/Columns button group.
afterActionsInjected after the button group.
filtersThe container for the active filters.
tableThe container for the actual table (wraps the <table> element and its border).
theadThe <thead> element.
tbodyThe <tbody> element.
footerThe container for the content below the table (e.g., pagination).
emptyStateThe empty state shown when there are no records. See Empty State.

Each of these slots receives a table and actions prop in its scope. These correspond to the useTable() and useActions() composables documented in the Custom Table Component section.

Additional dynamic slots are documented on their respective pages: custom filter components, image slots, and image fallback slots.

Example

vue
<Table :resource="users">
    <template #filters="{ table, actions }">
        <p v-if="!table.hasFilters">No filters applied.</p>
        <p v-if="actions.allItemsAreSelected">All items are selected!</p>
    </template>
</Table>
jsx
<Table
    resource={users}
    filters={({ table, actions }) => {
        return (
            <>
                <p>{table.hasFilters ? 'Filters applied!' : 'No filters applied.'}</p>
                <p>{actions.allItemsAreSelected ? 'All items are selected!' : ''}</p>
            </>
        )
    }}
/>

Topbar Slots v4

Four slots let you inject content around the search input and the action buttons. The search input and its slots (beforeSearch, afterSearch) are grouped in one <div>, and the action buttons and their slots (beforeActions, afterActions) are grouped in another. The flex gap between the two groups is preserved.

vue
<Table :resource="users">
    <template #beforeSearch>
        <Link href="/users/create">Create User</Link>
    </template>
    <template #afterActions>
        <button @click="doSomething">Custom Action</button>
    </template>
</Table>
jsx
<Table
    resource={users}
    beforeSearch={() => <Link href="/users/create">Create User</Link>}
    afterActions={() => <button onClick={doSomething}>Custom Action</button>}
/>

Using Exported UI Components

The package exports several UI primitives so your topbar additions can match the table's own styling.

js
import { Button, Dropdown, DropdownButton, DropdownHeader, DropdownItem, DropdownSeparator } from '@inertiaui/table-vue'
js
import { Button, Dropdown, DropdownButton, DropdownHeader, DropdownItem, DropdownSeparator } from '@inertiaui/table-react'

Column Slots

Instead of replacing a whole section of the table, you may replace individual column headers and cells. In Vue, use dynamic slot names that correspond to the column key: header(key) for headers and cell(key) for cells. In React, use the header and cell props and pass an object keyed by the column attribute.

Besides the table and actions props, header also receives a column prop that contains the column definition. In addition, cell receives column, item, and value props.

Example

vue
<Table :resource="users">
    <template #header(name)="{ column }">
        <b>Full name</b>
    </template>

    <template #cell(name)="{ column, item, value }">
        <span :title="value">{{ item.first_name }} {{ item.last_name }}</span>
    </template>
</Table>
jsx
<Table
    resource={users}
    header={{
        name: ({ column }) => <b>Full name</b>
    }}
    cell={{
        name: ({ column, item, value }) => <span title={value}>{item.first_name} {item.last_name}</span>
    }}
/>

Metadata

You may attach metadata to Actions and Links, Columns, Exports, and Filters. The default Table component ignores this metadata, but it's useful when extending the Table component via slots.