Builder
Introduction
Similar to a repeater, the builder component allows you to output a JSON array of repeated form components. Unlike the repeater, which only defines one form schema to repeat, the builder allows you to define different schema "blocks", which you can repeat in any order. This makes it useful for building more advanced array structures.
The primary use of the builder component is to build web page content using predefined blocks. This could be content for a marketing website, or maybe even fields in an online form. The example below defines multiple blocks for different elements in the page content. On the frontend of your website, you could loop through each block in the JSON and format it how you wish.
use Filament\Forms\Components\Builder;
use Filament\Forms\Components\Builder\Block;
use Filament\Forms\Components\FileUpload;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\Textarea;
use Filament\Forms\Components\TextInput;
Builder::make('content')
->blocks([
Block::make('heading')
->schema([
TextInput::make('content')
->label('Heading')
->required(),
Select::make('level')
->options([
'h1' => 'Heading 1',
'h2' => 'Heading 2',
'h3' => 'Heading 3',
'h4' => 'Heading 4',
'h5' => 'Heading 5',
'h6' => 'Heading 6',
])
->required(),
])
->columns(2),
Block::make('paragraph')
->schema([
Textarea::make('content')
->label('Paragraph')
->required(),
]),
Block::make('image')
->schema([
FileUpload::make('url')
->label('Image')
->image()
->required(),
TextInput::make('alt')
->label('Alt text')
->required(),
]),
])

We recommend that you store builder data with a JSON column in your database. Additionally, if you're using Eloquent, make sure that column has an array cast.
As evident in the above example, blocks can be defined within the blocks() method of the component. Blocks are Builder\Block objects, and require a unique name, and a component schema:
use Filament\Forms\Components\Builder;
use Filament\Forms\Components\Builder\Block;
use Filament\Forms\Components\TextInput;
Builder::make('content')
->blocks([
Block::make('heading')
->schema([
TextInput::make('content')->required(),
// ...
]),
// ...
])
Setting a block's label
By default, the label of the block will be automatically determined based on its name. To override the block's label, you may use the label() method. Customizing the label in this way is useful if you wish to use a translation string for localization:
use Filament\Forms\Components\Builder\Block;
Block::make('heading')
->label(__('blocks.heading'))
Labelling builder items based on their content
You may add a label for a builder item using the same label() method. This method accepts a closure that receives the item's data in a $state variable. If $state is null, you should return the block label that should be displayed in the block picker. Otherwise, you should return a string to be used as the item label:
use Filament\Forms\Components\Builder\Block;
use Filament\Forms\Components\TextInput;
Block::make('heading')
->schema([
TextInput::make('content')
->live(onBlur: true)
->required(),
// ...
])
->label(function (?array $state): string {
if ($state === null) {
return 'Heading';
}
return $state['content'] ?? 'Untitled heading';
})
Any fields that you use from $state should be live() if you wish to see the item label update live as you use the form.
You can inject various utilities into the function passed to label() as parameters.
Learn more about utility injection.| Utility | Type | Parameter | Description |
|---|---|---|---|
| Field | Filament\Forms\Components\Field | $component | The current field component instance. |
| Get function | Filament\Schemas\Components\Utilities\Get | $get | A function for retrieving values from the current form data. Validation is not run. |
| Key | string | $key | The key for the current block. |
| Livewire | Livewire\Component | $livewire | The Livewire component instance. |
| Eloquent model FQN | ?string<Illuminate\Database\Eloquent\Model> | $model | The Eloquent model FQN for the current schema. |
| Operation | string | $operation | The current operation being performed by the schema. Usually <code>create</code>, <code>edit</code>, or <code>view</code>. |
| Raw state | mixed | $rawState | The current value of the field, before state casts were applied. Validation is not run. |
| Eloquent record | ?Illuminate\Database\Eloquent\Model | $record | The Eloquent record for the current schema. |
| State | array<string, mixed> | $state | The raw unvalidated data for the current block. |

Numbering builder items
By default, items in the builder have a number next to their label. You may disable this using the blockNumbers(false) method:
use Filament\Forms\Components\Builder;
Builder::make('content')
->blocks([
// ...
])
->blockNumbers(false)
As well as allowing a static value, the blockNumbers() method also accepts a function to dynamically calculate it. You can inject various utilities into the function as parameters.
Learn more about utility injection.| Utility | Type | Parameter | Description |
|---|---|---|---|
| Field | Filament\Forms\Components\Field | $component | The current field component instance. |
| Get function | Filament\Schemas\Components\Utilities\Get | $get | A function for retrieving values from the current form data. Validation is not run. |
| Livewire | Livewire\Component | $livewire | The Livewire component instance. |
| Eloquent model FQN | ?string<Illuminate\Database\Eloquent\Model> | $model | The Eloquent model FQN for the current schema. |
| Operation | string | $operation | The current operation being performed by the schema. Usually <code>create</code>, <code>edit</code>, or <code>view</code>. |
| Raw state | mixed | $rawState | The current value of the field, before state casts were applied. Validation is not run. |
| Eloquent record | ?Illuminate\Database\Eloquent\Model | $record | The Eloquent record for the current schema. |
| State | mixed | $state | The current value of the field. Validation is not run. |
Setting a block's icon
Blocks may also have an icon, which is displayed next to the label. You can add an icon by passing its name to the icon() method:
use Filament\Forms\Components\Builder\Block;
use Filament\Support\Icons\Heroicon;
Block::make('paragraph')
->icon(Heroicon::Bars3BottomLeft)
As well as allowing a static value, the icon() method also accepts a function to dynamically calculate it. You can inject various utilities into the function as parameters.
Learn more about utility injection.| Utility | Type | Parameter | Description |
|---|---|---|---|
| Field | Filament\Forms\Components\Field | $component | The current field component instance. |
| Get function | Filament\Schemas\Components\Utilities\Get | $get | A function for retrieving values from the current form data. Validation is not run. |
| Livewire | Livewire\Component | $livewire | The Livewire component instance. |
| Eloquent model FQN | ?string<Illuminate\Database\Eloquent\Model> | $model | The Eloquent model FQN for the current schema. |
| Operation | string | $operation | The current operation being performed by the schema. Usually <code>create</code>, <code>edit</code>, or <code>view</code>. |
| Raw state | mixed | $rawState | The current value of the field, before state casts were applied. Validation is not run. |
| Eloquent record | ?Illuminate\Database\Eloquent\Model | $record | The Eloquent record for the current schema. |
| State | mixed | $state | The current value of the field. Validation is not run. |
Adding icons to the header of blocks
By default, blocks in the builder don't have an icon next to the header label, just in the dropdown to add new blocks. You may enable this using the blockIcons() method:
use Filament\Forms\Components\Builder;
Builder::make('content')
->blocks([
// ...
])
->blockIcons()
Optionally, you may pass a boolean value to the blockIcons() method to control if the icons are displayed in the block headers:
use Filament\Forms\Components\Builder;
Builder::make('content')
->blocks([
// ...
])
->blockIcons(FeatureFlag::active())
As well as allowing a static value, the blockIcons() method also accepts a function to dynamically calculate it. You can inject various utilities into the function as parameters.
Learn more about utility injection.| Utility | Type | Parameter | Description |
|---|---|---|---|
| Field | Filament\Forms\Components\Field | $component | The current field component instance. |
| Get function | Filament\Schemas\Components\Utilities\Get | $get | A function for retrieving values from the current form data. Validation is not run. |
| Livewire | Livewire\Component | $livewire | The Livewire component instance. |
| Eloquent model FQN | ?string<Illuminate\Database\Eloquent\Model> | $model | The Eloquent model FQN for the current schema. |
| Operation | string | $operation | The current operation being performed by the schema. Usually <code>create</code>, <code>edit</code>, or <code>view</code>. |
| Raw state | mixed | $rawState | The current value of the field, before state casts were applied. Validation is not run. |
| Eloquent record | ?Illuminate\Database\Eloquent\Model | $record | The Eloquent record for the current schema. |
| State | mixed | $state | The current value of the field. Validation is not run. |
Previewing blocks
If you prefer to render read-only previews in the builder instead of the blocks' forms, you can use the blockPreviews() method. This will render each block's preview() instead of the form. Block data will be passed to the preview Blade view in a variable with the same name:
use Filament\Forms\Components\Builder;
use Filament\Forms\Components\Builder\Block;
use Filament\Forms\Components\TextInput;
Builder::make('content')
->blockPreviews()
->blocks([
Block::make('heading')
->schema([
TextInput::make('text')
->placeholder('Default heading'),
])
->preview('filament.content.block-previews.heading'),
])
In /resources/views/filament/content/block-previews/heading.blade.php, you can access the block data like so:
<h1>
{{ $text ?? 'Default heading' }}
</h1>
Optionally, the blockPreviews() method accepts a boolean value to control if the builder should render block previews or not:
use Filament\Forms\Components\Builder;
Builder::make('content')
->blocks([
// ...
])
->blockPreviews(FeatureFlag::active())
As well as allowing static values, the blockPreviews() and preview() methods also accept functions to dynamically calculate them. You can inject various utilities into the function as parameters.
Learn more about utility injection.| Utility | Type | Parameter | Description |
|---|---|---|---|
| Field | Filament\Forms\Components\Field | $component | The current field component instance. |
| Get function | Filament\Schemas\Components\Utilities\Get | $get | A function for retrieving values from the current form data. Validation is not run. |
| Livewire | Livewire\Component | $livewire | The Livewire component instance. |
| Eloquent model FQN | ?string<Illuminate\Database\Eloquent\Model> | $model | The Eloquent model FQN for the current schema. |
| Operation | string | $operation | The current operation being performed by the schema. Usually <code>create</code>, <code>edit</code>, or <code>view</code>. |
| Raw state | mixed | $rawState | The current value of the field, before state casts were applied. Validation is not run. |
| Eloquent record | ?Illuminate\Database\Eloquent\Model | $record | The Eloquent record for the current schema. |
| State | mixed | $state | The current value of the field. Validation is not run. |
Interactive block previews
By default, preview content is not interactive, and clicking it will open the Edit modal for that block to manage its settings. If you have links and buttons that you'd like to remain interactive in the block previews, you can use the areInteractive: true argument of the blockPreviews() method:
use Filament\Forms\Components\Builder;
Builder::make('content')
->blockPreviews(areInteractive: true)
->blocks([
//
])
As well as allowing a static value, the areInteractive argument also accepts a function to dynamically calculate it. You can inject various utilities into the function as parameters.
Learn more about utility injection.| Utility | Type | Parameter | Description |
|---|---|---|---|
| Field | Filament\Forms\Components\Field | $component | The current field component instance. |
| Get function | Filament\Schemas\Components\Utilities\Get | $get | A function for retrieving values from the current form data. Validation is not run. |
| Livewire | Livewire\Component | $livewire | The Livewire component instance. |
| Eloquent model FQN | ?string<Illuminate\Database\Eloquent\Model> | $model | The Eloquent model FQN for the current schema. |
| Operation | string | $operation | The current operation being performed by the schema. Usually <code>create</code>, <code>edit</code>, or <code>view</code>. |
| Raw state | mixed | $rawState | The current value of the field, before state casts were applied. Validation is not run. |
| Eloquent record | ?Illuminate\Database\Eloquent\Model | $record | The Eloquent record for the current schema. |
| State | mixed | $state | The current value of the field. Validation is not run. |
Adding items
An action button is displayed below the builder to allow the user to add a new item.
Setting the add action button's label
You may set a label to customize the text that should be displayed in the button for adding a builder item, using the addActionLabel() method:
use Filament\Forms\Components\Builder;
Builder::make('content')
->blocks([
// ...
])
->addActionLabel('Add a new block')
As well as allowing a static value, the addActionLabel() method also accepts a function to dynamically calculate it. You can inject various utilities into the function as parameters.
Learn more about utility injection.| Utility | Type | Parameter | Description |
|---|---|---|---|
| Field | Filament\Forms\Components\Field | $component | The current field component instance. |
| Get function | Filament\Schemas\Components\Utilities\Get | $get | A function for retrieving values from the current form data. Validation is not run. |
| Livewire | Livewire\Component | $livewire | The Livewire component instance. |
| Eloquent model FQN | ?string<Illuminate\Database\Eloquent\Model> | $model | The Eloquent model FQN for the current schema. |
| Operation | string | $operation | The current operation being performed by the schema. Usually <code>create</code>, <code>edit</code>, or <code>view</code>. |
| Raw state | mixed | $rawState | The current value of the field, before state casts were applied. Validation is not run. |
| Eloquent record | ?Illuminate\Database\Eloquent\Model | $record | The Eloquent record for the current schema. |
| State | mixed | $state | The current value of the field. Validation is not run. |
Aligning the add action button
By default, the add action is aligned in the center. You may adjust this using the addActionAlignment() method, passing an Alignment option of Alignment::Start or Alignment::End:
use Filament\Forms\Components\Builder;
use Filament\Support\Enums\Alignment;
Builder::make('content')
->schema([
// ...
])
->addActionAlignment(Alignment::Start)
As well as allowing a static value, the addActionAlignment() method also accepts a function to dynamically calculate it. You can inject various utilities into the function as parameters.
Learn more about utility injection.| Utility | Type | Parameter | Description |
|---|---|---|---|
| Field | Filament\Forms\Components\Field | $component | The current field component instance. |
| Get function | Filament\Schemas\Components\Utilities\Get | $get | A function for retrieving values from the current form data. Validation is not run. |
| Livewire | Livewire\Component | $livewire | The Livewire component instance. |
| Eloquent model FQN | ?string<Illuminate\Database\Eloquent\Model> | $model | The Eloquent model FQN for the current schema. |
| Operation | string | $operation | The current operation being performed by the schema. Usually <code>create</code>, <code>edit</code>, or <code>view</code>. |
| Raw state | mixed | $rawState | The current value of the field, before state casts were applied. Validation is not run. |
| Eloquent record | ?Illuminate\Database\Eloquent\Model | $record | The Eloquent record for the current schema. |
| State | mixed | $state | The current value of the field. Validation is not run. |
Preventing the user from adding items
You may prevent the user from adding items to the builder using the addable(false) method:
use Filament\Forms\Components\Builder;
Builder::make('content')
->blocks([
// ...
])
->addable(false)
As well as allowing a static value, the addable() method also accepts a function to dynamically calculate it. You can inject various utilities into the function as parameters.
Learn more about utility injection.| Utility | Type | Parameter | Description |
|---|---|---|---|
| Field | Filament\Forms\Components\Field | $component | The current field component instance. |
| Get function | Filament\Schemas\Components\Utilities\Get | $get | A function for retrieving values from the current form data. Validation is not run. |
| Livewire | Livewire\Component | $livewire | The Livewire component instance. |
| Eloquent model FQN | ?string<Illuminate\Database\Eloquent\Model> | $model | The Eloquent model FQN for the current schema. |
| Operation | string | $operation | The current operation being performed by the schema. Usually <code>create</code>, <code>edit</code>, or <code>view</code>. |
| Raw state | mixed | $rawState | The current value of the field, before state casts were applied. Validation is not run. |
| Eloquent record | ?Illuminate\Database\Eloquent\Model | $record | The Eloquent record for the current schema. |
| State | mixed | $state | The current value of the field. Validation is not run. |
Deleting items
An action button is displayed on each item to allow the user to delete it.
Preventing the user from deleting items
You may prevent the user from deleting items from the builder using the deletable(false) method:
use Filament\Forms\Components\Builder;
Builder::make('content')
->blocks([
// ...
])
->deletable(false)
As well as allowing a static value, the deletable() method also accepts a function to dynamically calculate it. You can inject various utilities into the function as parameters.
Learn more about utility injection.| Utility | Type | Parameter | Description |
|---|---|---|---|
| Field | Filament\Forms\Components\Field | $component | The current field component instance. |
| Get function | Filament\Schemas\Components\Utilities\Get | $get | A function for retrieving values from the current form data. Validation is not run. |
| Livewire | Livewire\Component | $livewire | The Livewire component instance. |
| Eloquent model FQN | ?string<Illuminate\Database\Eloquent\Model> | $model | The Eloquent model FQN for the current schema. |
| Operation | string | $operation | The current operation being performed by the schema. Usually <code>create</code>, <code>edit</code>, or <code>view</code>. |
| Raw state | mixed | $rawState | The current value of the field, before state casts were applied. Validation is not run. |
| Eloquent record | ?Illuminate\Database\Eloquent\Model | $record | The Eloquent record for the current schema. |
| State | mixed | $state | The current value of the field. Validation is not run. |
Reordering items
A button is displayed on each item to allow the user to drag and drop to reorder it in the list.
Preventing the user from reordering items
You may prevent the user from reordering items from the builder using the reorderable(false) method:
use Filament\Forms\Components\Builder;
Builder::make('content')
->blocks([
// ...
])
->reorderable(false)
As well as allowing a static value, the reorderable() method also accepts a function to dynamically calculate it. You can inject various utilities into the function as parameters.
Learn more about utility injection.| Utility | Type | Parameter | Description |
|---|---|---|---|
| Field | Filament\Forms\Components\Field | $component | The current field component instance. |
| Get function | Filament\Schemas\Components\Utilities\Get | $get | A function for retrieving values from the current form data. Validation is not run. |
| Livewire | Livewire\Component | $livewire | The Livewire component instance. |
| Eloquent model FQN | ?string<Illuminate\Database\Eloquent\Model> | $model | The Eloquent model FQN for the current schema. |
| Operation | string | $operation | The current operation being performed by the schema. Usually <code>create</code>, <code>edit</code>, or <code>view</code>. |
| Raw state | mixed | $rawState | The current value of the field, before state casts were applied. Validation is not run. |
| Eloquent record | ?Illuminate\Database\Eloquent\Model | $record | The Eloquent record for the current schema. |
| State | mixed | $state | The current value of the field. Validation is not run. |
Reordering items with buttons
You may use the reorderableWithButtons() method to enable reordering items with buttons to move the item up and down:
use Filament\Forms\Components\Builder;
Builder::make('content')
->blocks([
// ...
])
->reorderableWithButtons()

Optionally, you may pass a boolean value to control if the builder should be ordered with buttons or not:
use Filament\Forms\Components\Builder;
Builder::make('content')
->blocks([
// ...
])
->reorderableWithButtons(FeatureFlag::active())
As well as allowing a static value, the reorderableWithButtons() method also accepts a function to dynamically calculate it. You can inject various utilities into the function as parameters.
Learn more about utility injection.| Utility | Type | Parameter | Description |
|---|---|---|---|
| Field | Filament\Forms\Components\Field | $component | The current field component instance. |
| Get function | Filament\Schemas\Components\Utilities\Get | $get | A function for retrieving values from the current form data. Validation is not run. |
| Livewire | Livewire\Component | $livewire | The Livewire component instance. |
| Eloquent model FQN | ?string<Illuminate\Database\Eloquent\Model> | $model | The Eloquent model FQN for the current schema. |
| Operation | string | $operation | The current operation being performed by the schema. Usually <code>create</code>, <code>edit</code>, or <code>view</code>. |
| Raw state | mixed | $rawState | The current value of the field, before state casts were applied. Validation is not run. |
| Eloquent record | ?Illuminate\Database\Eloquent\Model | $record | The Eloquent record for the current schema. |
| State | mixed | $state | The current value of the field. Validation is not run. |
Preventing reordering with drag and drop
You may use the reorderableWithDragAndDrop(false) method to prevent items from being ordered with drag and drop:
use Filament\Forms\Components\Builder;
Builder::make('content')
->blocks([
// ...
])
->reorderableWithDragAndDrop(false)


