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...