# Multi Select
@formField('multi_select', [
'name' => 'sectors',
'label' => 'Sectors',
'min' => 1,
'max' => 2,
'options' => [
[
'value' => 'arts',
'label' => 'Arts & Culture'
],
[
'value' => 'finance',
'label' => 'Banking & Finance'
],
[
'value' => 'civic',
'label' => 'Civic & Public'
],
[
'value' => 'design',
'label' => 'Design & Architecture'
],
[
'value' => 'education',
'label' => 'Education'
]
]
])
Option | Description | Type/values | Default value |
---|---|---|---|
name | Name of the field | string | |
label | Label of the field | string | |
min | Minimum number of selectable options | integer | |
max | Maximum number of selectable options | integer | |
options | Array of options for the dropdown, must include value and label | array | |
unpack | Defines if the multi select will be displayed as an open list of options | true false | true |
columns | Aligns the options on a grid with a given number of columns | integer | 0 (off) |
searchable | Filter the field values while typing | true false | false |
note | Hint message displayed above the field | string | |
placeholder | Text displayed as a placeholder in the field | string | |
required | Displays an indicator that this field is required A backend validation rule is required to prevent users from saving | true false | false |
disabled | Disables the field | true false | false |
There are several ways to implement a multi_select
form field.
# Multi select with static values
Sometimes you just have a set of values that are static.
In this case that it can be implemented as follows:
- Create the database migration to store a JSON or LONGTEXT:
Schema::table('posts', function (Blueprint $table) {
...
$table->json('sectors')->nullable();
...
});
// OR
Schema::table('posts', function (Blueprint $table) {
...
$table->longtext('sectors')->nullable();
...
});
- In your model add an accessor and a mutator:
public function getSectorsAttribute($value)
{
return collect(json_decode($value))->map(function($item) {
return ['id' => $item];
})->all();
}
public function setSectorsAttribute($value)
{
$this->attributes['sectors'] = collect($value)->filter()->values();
}
- Cast the field to
array
:
protected $casts = [
'sectors' => 'array'
]
# Multi select with dynamic values
Sometimes the content for the multi_select
is coming from another model.
In this case that it can be implemented as follows:
- Create a Sectors module
php artisan twill:make:module sectors
- Create a migration for a pivot table.
php artisan make:migration create_post_sector_table
- Use Twill's
createDefaultRelationshipTableFields
to set it up:
public function up()
{
Schema::create('post_sector', function (Blueprint $table) {
createDefaultRelationshipTableFields($table, 'sector', 'post');
$table->integer('position')->unsigned()->index();
});
}
- In your model, add a
belongsToMany
relationship:
public function sectors() {
return $this->belongsToMany('App\Models\Sector');
}
- In your repository, make sure to sync the association when saving:
public function afterSave($object, $fields)
{
$object->sectors()->sync($fields['sectors'] ?? []);
parent::afterSave($object, $fields);
}
- In your controller, add to the formData the collection of options:
protected function formData($request)
{
return [
'sectors' => app()->make(SectorRepository::class)->listAll()
];
}
- In the form, we can now add the field:
@formField('multi_select', [
'name' => 'sectors',
'label' => 'Sectors',
'options' => $sectors
])
When used in a block, no migration is needed.