Filament Infolist: Custom Entry with "Show More" Button

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

Like our articles?

Become a Premium Member for $129/year or $29/month
What else you will get:
  • 56 courses (1011 lessons, total 46 h 42 min)
  • 77 long-form tutorials (one new every week)
  • access to project repositories
  • access to private Discord

Recent Premium Tutorials