Files
filament/packages/forms/docs/03-fields/12-repeater.md
T
2022-11-01 22:19:11 +00:00

6.5 KiB

title
title
Repeater

The repeater component allows you to output a JSON array of repeated form components.

use Filament\Forms\Components\Repeater;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;

Repeater::make('members')
    ->schema([
        TextInput::make('name')->required(),
        Select::make('role')
            ->options([
                'member' => 'Member',
                'administrator' => 'Administrator',
                'owner' => 'Owner',
            ])
            ->required(),
    ])
    ->columns(2)

We recommend that you store repeater 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, the component schema can be defined within the schema() method of the component:

use Filament\Forms\Components\Repeater;
use Filament\Forms\Components\TextInput;

Repeater::make('members')
    ->schema([
        TextInput::make('name')->required(),
        // ...
    ])

If you wish to define a repeater with multiple schema blocks that can be repeated in any order, please use the builder.

Repeaters may have a certain number of empty items created by default, using the defaultItems() method:

use Filament\Forms\Components\Repeater;

Repeater::make('members')
    ->schema([
        // ...
    ])
    ->defaultItems(3)

You may set a label to customize the text that should be displayed in the button for adding a repeater item:

use Filament\Forms\Components\Repeater;

Repeater::make('members')
    ->schema([
        // ...
    ])
    ->createItemButtonLabel('Add member')

You may also prevent the user from adding items, deleting items, or moving items inside the repeater:

use Filament\Forms\Components\Repeater;

Repeater::make('members')
    ->schema([
        // ...
    ])
    ->disableItemCreation()
    ->disableItemDeletion()
    ->disableItemMovement()

You may customize the number of items that may be created, using the minItems() and maxItems() methods:

use Filament\Forms\Components\Repeater;

Repeater::make('members')
    ->schema([
        // ...
    ])
    ->minItems(1)
    ->maxItems(10)

Collapsible

The repeater may be collapsible() to optionally hide content in long forms:

use Filament\Forms\Components\Repeater;

Repeater::make('qualifications')
    ->schema([
        // ...
    ])
    ->collapsible()

You may collapse all items by default:

use Filament\Forms\Components\Repeater;

Repeater::make('qualifications')
    ->schema([
        // ...
    ])
    ->collapsed()

Cloning items

You may allow repeater items to be duplicated using the cloneable() method:

use Filament\Forms\Components\Repeater;

Repeater::make('qualifications')
    ->schema([
        // ...
    ])
    ->cloneable()

Populating automatically from a relationship

You may employ the relationship() method of the repeater to configure a relationship to automatically retrieve and save repeater items:

use Filament\Forms\Components\Repeater;

Repeater::make('qualifications')
    ->relationship()
    ->schema([
        // ...
    ])

To set this functionality up, you must also follow the instructions set out in the field relationships section. If you're using the admin panel, you can skip this step.

Ordering items

By default, ordering relationship repeater items is disabled. This is because your related model needs an sort column to store the order of related records. To enable ordering, you may use the orderable() method:

use Filament\Forms\Components\Repeater;

Repeater::make('qualifications')
    ->relationship()
    ->schema([
        // ...
    ])
    ->orderable()

This assumes that your related model has a sort column.

If you use something like spatie/eloquent-sortable with an order column such as order_column, you may pass this in to orderable():

use Filament\Forms\Components\Repeater;

Repeater::make('qualifications')
    ->relationship()
    ->schema([
        // ...
    ])
    ->orderable('order_column')

Grid layout

You may organize repeater items into columns by using the grid() method:

use Filament\Forms\Components\Repeater;

Repeater::make('members')
    ->schema([
        // ...
    ])
    ->grid(2)

This method accepts the same options as the columns() method of the grid. This allows you to responsively customize the number of grid columns at various breakpoints.

Item labels

You may add a label for repeater items using the itemLabel() method:

use Filament\Forms\Components\Repeater;
use Filament\Forms\Components\TextInput;

Repeater::make('members')
    ->schema([
        TextInput::make('name')
            ->lazy(),
    ])
    ->itemLabel(fn (array $state): ?string => $state['name'] ?? null),

Any fields that you use from $state should be reactive() or lazy() if you wish to see the item label update live as you use the form.

Using $get() to access parent field values

All form components are able to use $get() and $set() to access another field's value. However, you might experience unexpected behaviour when using this inside the repeater's schema.

This is because $get() and $set(), by default, are scoped to the current repeater item. This means that you are able to interact with another field inside that repeater item easily without knowing which repeater item the current form component belongs to.

The consequence of this, is that you may be confused when you are unable to interact with a field outside the repeater. We use ../ syntax to solve this problem - $get('../../parent_field_name').

Consider your form has this data structure:

[
    'client_id' => 1,

    'repeater' => [
        'item1' => [
            'service_id' => 2,
        ],
    ],
]

You are trying to retrieve the value of client_id from inside the repeater item.

$get() is relative to the current repeater item, so $get('client_id') is looking for $get('repeater.item1.client_id').

You can use ../ to go up a level in the data structure, so $get('../client_id') is $get('repeater.client_id') and $get('../../client_id') is $get('client_id').