Custom data
Introduction
Filament's table builder was originally designed to render data directly from a SQL database using Eloquent models in a Laravel application. Each row in a Filament table corresponds to a row in the database, represented by an Eloquent model instance.
However, this setup isn't always possible or practical. You might need to display data that isn't stored in a database—or data that is stored, but not accessible via Eloquent.
In such cases, you can use custom data instead. Pass a function to the records() method of the table builder that returns an array of data. This function is called when the table renders, and the value it returns is used to populate the table.
use Filament\Tables\Columns\IconColumn;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
public function table(Table $table): Table
{
return $table
->records(fn (): array => [
1 => [
'title' => 'First item',
'slug' => 'first-item',
'is_featured' => true,
],
2 => [
'title' => 'Second item',
'slug' => 'second-item',
'is_featured' => false,
],
3 => [
'title' => 'Third item',
'slug' => 'third-item',
'is_featured' => true,
],
])
->columns([
TextColumn::make('title'),
TextColumn::make('slug'),
IconColumn::make('is_featured')
->boolean(),
]);
}
NOTE
The array keys (e.g., 1, 2, 3) represent the record IDs. Use unique and consistent keys to ensure proper diffing and state tracking. This helps prevent issues with record integrity during Livewire interactions and updates.
Columns
Columns in the table work similarly to how they do when using Eloquent models, but with one key difference: instead of referring to a model attribute or relationship, the column name represents a key in the array returned by the records() function.
When working with the current record inside a column function, set the $record type to array instead of Model. For example, to define a column using the state() function, you could do the following:
use Filament\Tables\Columns\TextColumn;
TextColumn::make('is_featured')
->state(function (array $record): string {
return $record['is_featured'] ? 'Featured' : 'Not featured';
})
Sorting
Filament's built-in sorting function uses SQL to sort data. When working with custom data, you'll need to handle sorting yourself.
To access the currently sorted column and direction, you can inject $sortColumn and $sortDirection into the records() function. These variables are null if no sorting is applied.
In the example below, a collection is used to sort the data by key. The collection is returned instead of an array, and Filament handles it the same way. However, using a collection is not required to use this feature.
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
use Illuminate\Support\Collection;
public function table(Table $table): Table
{
return $table
->records(
fn (?string $sortColumn, ?string $sortDirection): Collection => collect([
1 => ['title' => 'First item'],
2 => ['title' => 'Second item'],
3 => ['title' => 'Third item'],
])->when(
filled($sortColumn),
fn (Collection $data): Collection => $data->sortBy(
$sortColumn,
SORT_REGULAR,
$sortDirection === 'desc',
),
)
)
->columns([
TextColumn::make('title')
->sortable(),
]);
}
NOTE
It might seem like Filament should sort the data for you, but in many cases, it's better to let your data source—like a custom query or API call—handle the sorting instead.