# Custom columns

> Add a React cell renderer and prepare its values or metadata in Laravel.

Source: https://docs.inertiax.dev/table/guide/custom-columns/

For a different cell appearance, give the column a namespaced type and register a matching renderer. Use [built-in formatting](https://docs.inertiax.dev/table/guide/columns/#transform-values) when only the value needs to change.

## Declare the type

**Laravel**

```php
use InertiaX\Table\Columns\TextColumn;

TextColumn::make('role')->type('acme/role');
```

The key `role` still selects the source field. The type `acme/role` selects the React renderer.

## Render the cell

**React**

```tsx
import {
  register,
  type TableCellRendererProps,
  type TableCustomizationOptions,
} from '@inertiax/react-table';
import { AppTable } from '@/components/app-table';

function RoleCell({ cell }: TableCellRendererProps) {
  return <strong>{String(cell.value ?? '')}</strong>;
}

const customization = {
  cellRenderers: [register('acme/role', RoleCell)],
} satisfies TableCustomizationOptions;

export function UsersIndex() {
  return <AppTable prop="users" customization={customization} />;
}
```

Pass the same customization object to `TableProvider` to register it across the application. See [Registration & diagnostics](https://docs.inertiax.dev/table/guide/registration/) for scope and missing-renderer behavior.

For Eloquent and collections, a searchable column with a custom type needs a [`searchUsing()` callback](https://docs.inertiax.dev/table/guide/query-callbacks/#search-a-stored-field), even when created with `TextColumn`. With a custom source, searchable columns must keep `type('text')`; see [Custom-source search](https://docs.inertiax.dev/table/reference/source/#search).

## Link to a record

A cell renderer also receives the row’s ID, so a cell can link to the record’s page:

**Laravel**

```php
TextColumn::make('name')->type('acme/user-link');
```

**React**

```tsx
import { Link } from '@inertiajs/react';
import {
  register,
  type TableCellRendererProps,
  type TableCustomizationOptions,
} from '@inertiax/react-table';
import { AppTable } from '@/components/app-table';

function UserLinkCell({ cell, rowId }: TableCellRendererProps) {
  return <Link href={`/users/${rowId}`}>{String(cell.value ?? '')}</Link>;
}

const customization = {
  cellRenderers: [register('acme/user-link', UserLinkCell)],
} satisfies TableCustomizationOptions;

export function UsersIndex() {
  return <AppTable prop="users" customization={customization} />;
}
```

`rowId` is the row’s key: the model’s primary key, or the field the table names with `rowKey()`. Use your own route helper for the URL. An edit or delete button works the same way; see [Authorization & security](https://docs.inertiax.dev/table/guide/security/#validate-actions-independently) for its endpoint.

## Add row-specific metadata

Column `meta()` supplies configuration shared by all rows. A cell decorator can supply metadata for one row:

**Laravel**

```php
use InertiaX\Table\Columns\CellPayload;

TextColumn::make('role')
    ->type('acme/role')
    ->meta('compact', true)
    ->decorateUsing(function (CellPayload $cell): CellPayload {
        return $cell->putProperty('emphasized', $cell->value === 'admin');
    });
```

The renderer reads `column.meta` and `cell.meta` respectively. Cell renderer props also include `rowId`. All metadata reaches the browser; follow the [field exposure rules](https://docs.inertiax.dev/table/guide/security/#choose-fields-deliberately).

See [Column API](https://docs.inertiax.dev/table/reference/column/#cell-decorators) for reusable decorator classes and stage ordering.
