Skip to content

Controller and events

Most pages should let the built-in controls drive the Table. Use the controller when application UI outside the Table needs to perform the same canonical transitions.

import { type TableController } from '@inertiax/core';
import { InertiaX } from '@inertiax/react-inertia';
import { useRef } from 'react';
export function UsersTable() {
const controllerRef = useRef<TableController>(null);
return (
<>
<button onClick={() => controllerRef.current?.refresh()}>
Refresh users
</button>
<InertiaX prop="users" controllerRef={controllerRef} />
</>
);
}

The ref is set while the renderer owns the session and cleared on unmount.

The public controller exposes:

  • getState();
  • setPage() and setPageSize();
  • setSorting(), setFilters(), and setSearch();
  • getSelection(), setSelection(), and clearSelection();
  • getColumnVisibility(), setColumnVisibility(), and resetColumnVisibility();
  • refresh() and retry().

These operations validate state and use the configured integration. Do not mutate the returned state object or construct Inertia URLs yourself.

Inside a custom renderer region, use useTableController() instead of threading the ref.

Event handlers can be application-scoped or component-scoped:

<InertiaX
prop="users"
table={{
events: {
selectionChange(event) {
console.log(event.selection);
},
requestError(event) {
reportError(event.error);
},
copySuccess(event) {
analytics.track('table_cell_copied', {
column: event.columnKey,
row: event.rowId,
});
},
},
}}
/>

The eight supported event keys are:

Event Emitted when
stateChange canonical state changes from a transition, location, or result
requestStart an integration request begins
requestSuccess the accepted latest request succeeds
requestError the accepted latest request fails
selectionChange selected row IDs change
columnVisibilityChange the visibility map changes
copySuccess a cell value is copied
copyError copying fails

Provider and component handlers both observe their scope. Events are immutable snapshots. Treat them as notifications; dispatch new state through the controller rather than modifying an event.

Custom content inside the renderer can subscribe through hooks:

function SelectionSummary() {
const state = useTableState();
const controller = useTableController();
return (
<button onClick={() => controller.clearSelection()}>
Clear {state.selection.length} selected rows
</button>
);
}

Use useTableSnapshot() when state, envelope, and request status must be read atomically. Use the narrower hooks when a component needs only one part.

Selection and events do not perform application actions automatically. Your application decides what a selected row means and how a domain operation is authorized and submitted.