How to Make a Filament Table Column Both Clickable and Copyable
James Manager
In Filament, TextColumn is one of the most powerful table column types. You can make it clickable with ->url() or copyable with ->copyable(). But what if you want both behaviors in the same column?
- Clicking the text → navigate to the order page.
- Clicking the icon → copy the order number.
By default, copyable() overrides url(), so you can’t use them together.
Here’s a neat hack I used recently to solve this.
The Problem
Tables\Columns\TextColumn::make('id')
->url(fn (Order $record) => url("/orders/{$record->id}"))
->icon('heroicon-m-clipboard')
->copyable();
Looks good, but in practice:
- If you add copyable(), the whole column becomes copy-only.
- If you keep url(), the icon is just decorative.
We need a way to tell Filament:
👉 Text = link
👉 Icon = copy
The Hack with extraAttributes()
TextColumn has an extraAttributes() method that lets you attach AlpineJS to the rendered column. We can use event delegation:
- Detect if the click is on the <svg> icon → copy to clipboard.
- Otherwise, fall back to navigating to the URL.
Here’s the working code:
Tables\Columns\TextColumn::make('id')
->label('Order')
->formatStateUsing(fn ($state, Order $record) => $record->number)
->description(fn (Order $record) => $record->user->number)
->sortable()
->url(fn (Order $record) => url("/orders/{$record->id}"))
->icon('heroicon-m-clipboard')
->iconPosition(\Filament\Tables\Columns\TextColumn\IconPosition::After)
->iconColor('gray')
->extraAttributes(fn (Order $record) => [
'x-data' => '{}',
'x-on:click.prevent' => "
if (\$event.target.closest('svg')) {
navigator.clipboard.writeText('{$record->number}');
\$tooltip('Copied to clipboard', { timeout: 1500 });
} else {
window.location.href = '/orders/{$record->id}';
}
",
]);
The Result
- ✅ Clicking the order number takes you to the order page.
- ✅ Clicking the clipboard icon copies the order number and shows a tooltip: “Copied to clipboard”.
- ✅ Keeps all the benefits of TextColumn — sortable, searchable, description, etc.
Share this article
Related Articles
Laravel Filament: How to Properly Sort by Pivot Table Columns
Learn how to correctly sort related records in Filament without MySQL errors by referencing the correct table in defaultSort
Troubleshooting Laravel Livewire: Resolving the 'Unable to Find Component' Error
Learn how to troubleshoot the "Unable to find component" error in Laravel Livewire. Follow our step-by-step guide to quickly resolve this common issue and get back to developing with ease.
Implementing a Single Custom Login Page for all Panels in FilamentPHP
Learn how to use custom page for login and registration across multiple panels in FilamentPHP.