# Repeater

@formField('repeater', ['type' => 'video'])
| Option | Description | Type | Default value |
|---|---|---|---|
| type | Type of repeater items | string | |
| name | Name of the field | string | same as type |
| max | Maximum amount that can be created | number | null (unlimited) |
| buttonAsLink | Displays the Add button as a centered link | boolean | false |
| reorder | Allow reordering of repeater items | boolean | true |
Repeater fields can be used inside as well as outside the block editor.
Inside the block editor, repeater blocks share the same model as regular blocks. By reading the section on the block editor first, you will get a good overview of how to create and define repeater blocks for your project. No migration is needed when using repeater blocks. Refer to the section titled Adding repeater fields to a block for a detailed explanation.
Outside the block editor, repeater fields are used to save hasMany or morphMany relationships.
# Using repeater fields
The following example demonstrates how to define a relationship between Team and TeamMember modules to implement a team-member repeater.
- Create the modules. Make sure to enable the
positionfeature on theTeamMembermodule:
php artisan twill:make:module Team
php artisan twill:make:module TeamMember -P
- Update the
create_team_members_tablesmigration. Add theteam_idforeign key used for theTeamMember—Teamrelationship:
class CreateTeamMembersTables extends Migration
{
public function up()
{
Schema::create('team_members', function (Blueprint $table) {
/* ... */
$table->foreignId('team_id')
->constrained()
->onUpdate('cascade')
->onDelete('cascade');
});
}
}
- Run the migrations:
php artisan migrate
- Update the
Teammodel. Define themembersrelationship. The results should be ordered by position:
class Team extends Model
{
/* ... */
public function members()
{
return $this->hasMany(TeamMember::class)->orderBy('position');
}
}
- Update the
TeamMembermodel. Addteam_idto thefillablearray:
class TeamMember extends Model
{
protected $fillable = [
/* ... */
'team_id',
];
}
- Update
TeamRepository. Override theafterSaveandgetFormFieldsmethods to process the repeater field:- Note: For Polymorphic relationships, use
updateRepeaterMorphManyin place ofupdateRepeater
- Note: For Polymorphic relationships, use
class TeamRepository extends ModuleRepository
{
/* ... */
public function afterSave($object, $fields)
{
$this->updateRepeater($object, $fields, 'members', 'TeamMember', 'team-member');
parent::afterSave($object, $fields);
}
public function getFormFields($object)
{
$fields = parent::getFormFields($object);
$fields = $this->getFormFieldsForRepeater($object, $fields, 'members', 'TeamMember', 'team-member');
return $fields;
}
}
- Add the repeater Blade template:
Create file resources/views/admin/repeaters/team-member.blade.php:
@twillRepeaterTitle('Team Member')
@twillRepeaterTrigger('Add member')
@twillRepeaterGroup('app')
@formField('input', [
'name' => 'title',
'label' => 'Title',
'required' => true,
])
...
- Add the repeater field to the form:
Update file resources/views/admin/teams/form.blade.php:
@extends('twill::layouts.form')
@section('contentFields')
...
@formField('repeater', ['type' => 'team-member'])
@stop
- Finishing up:
Add both modules to your admin.php routes. Add the Team module to your twill-navigation.php config and you are done!
# Dynamic repeater titles
In Twill >= 2.5, you can use the @twillRepeaterTitleField directive to include the value of a given field in the title of the repeater items. This directive also accepts a hidePrefix option to hide the generic repeater title:
@twillRepeaterTitle('Person')
@twillRepeaterTitleField('name', ['hidePrefix' => true])
@twillRepeaterTrigger('Add person')
@twillRepeaterGroup('app')
@formField('input', [
'name' => 'name',
'label' => 'Name',
'required' => true,
])