Filament 3 Infolist feature has a few entry types like TextEntry and others. But what if you need something custom? In this tutorial, we will create a custom Infolist entry to add a Show more
/Show less
button.
This is based on a question from our YouTube channel.
In this example, we have a Post Model with a title
and a body
.
First, we must create a custom infolist class.
php artisan make:infolist-layout PostBody
Now, we can call the newly created infolist entry in the Filament Resource infolist method.
use App\Infolists\Components\PostBody;use Filament\Infolists\Components\TextEntry; class PostResource extends Resource{ // ... public static function infolist(Infolist $infolist): Infolist { return $infolist ->schema([ TextEntry::make('title') ->columnSpanFull(), PostBody::make('body') ->columnSpanFull(), ]); } // ...}
We can use the {{ $getState() }}
in the view file to access the current state. Using Alpine.js, we can now add a button to show or hide trimmed text. Also, using Alpine.js, we will trim the text.
resources/views/infolists/components/post-body.blade.php:
<x-dynamic-component :component="$getEntryWrapperView()" :entry="$entry"> <div x-data="{ isCollapsed: false, maxLength: 20, originalContent: '', content: '' }" x-init="originalContent = @js($getState()); content = originalContent.slice(0, maxLength) + '...'" > <span x-text="isCollapsed ? originalContent : content"></span> <x-filament::button size="xs" color="gray" @click="isCollapsed = !isCollapsed" x-show="originalContent.length > maxLength" x-text="isCollapsed ? 'Show less' : 'Show more'" ></x-filament::button> </div></x-dynamic-component>
The view page shows our created custom infolist entry for a post body with a working Show more
/Show less
button.
We can also make the length of a text configurable. We must add a protected property in the PostBody
infolist entry. We will call it $maxLength
, and two public methods, maxLength
, and getMaxLength
.
app/Infolists/Components/PostBody.php:
class PostBody extends Entry{ protected string $view = 'infolists.components.post-body'; protected int | \Closure | null $maxLength = 20; public function maxLength(int | \Closure | null $maxLength): static { $this->maxLength = $maxLength; return $this; } public function getMaxLength(): ?int { return $this->evaluate($this->maxLength); } }
Now, we can call the maxLength
method in the resource when using the PostBody
entry.
class PostResource extends Resource{ // ... public static function infolist(Infolist $infolist): Infolist { return $infolist ->schema([ TextEntry::make('title') ->columnSpanFull(), PostBody::make('body') ->maxLength(50) ->columnSpanFull(), ]); } // ...}
In the view file, we must change the hard-coded maxLength
value to use provided. We need to use the $getMaxLength()
to get this value.
resources/views/infolists/components/post-body.blade.php:
<x-dynamic-component :component="$getEntryWrapperView()" :entry="$entry"> <div x-data="{ isCollapsed: false, maxLength: 20, originalContent: '', content: '' }" <div x-data="{ isCollapsed: false, maxLength: @js($getMaxLength()), originalContent: '', content: '' }" x-init="originalContent = @js($getState()); content = originalContent.slice(0, maxLength) + '...'" > <span x-text="isCollapsed ? originalContent : content"></span> <x-filament::button size="xs" color="gray" @click="isCollapsed = !isCollapsed" x-show="originalContent.length > maxLength" x-text="isCollapsed ? 'Show less' : 'Show more'" ></x-filament::button> </div></x-dynamic-component>
As you can see, the text is longer now.
The full source code is available in this GitHub repository.
If you want more Filament examples, you can find more real-life projects on our FilamentExamples.com.
No comments or questions yet...