
All Source and content copied and paste from their original documents.
Please follow those
Twill Doc- https://twill.io/docs/
Form fields – https://twill.io/docs/form-fields/
Your module form
view should look something like this (resources/views/admin/moduleName/form.blade.php
):
@extends('twill::layouts.form')
@section('contentFields')
@formField('...', [...])
...
@stop
Input
@formField('input', [
'name' => 'subtitle',
'label' => 'Subtitle',
'maxlength' => 100,
'required' => true,
'note' => 'Hint message goes here',
'placeholder' => 'Placeholder goes here',
])
@formField('input', [
'translated' => true,
'name' => 'subtitle_translated',
'label' => 'Subtitle (translated)',
'maxlength' => 250,
'required' => true,
'note' => 'Hint message goes here',
'placeholder' => 'Placeholder goes here',
'type' => 'textarea',
'rows' => 3
])
WYSIWYG
@formField('wysiwyg', [
'name' => 'case_study',
'label' => 'Case study text',
'toolbarOptions' => [
['header' => [2, 3, 4, 5, 6, false]],
'bold',
'italic',
'underline',
'strike',
["script" => "super"],
["script" => "sub"],
"blockquote",
"code-block",
['list' => 'ordered'],
['list' => 'bullet'],
['indent' => '-1'],
['indent' => '+1'],
["align" => []],
["direction" => "rtl"],
'link',
"clean",
],
'placeholder' => 'Case study text',
'maxlength' => 200,
'editSource' => true,
'note' => 'Hint message`',
])
Medias
@formField('medias', [
'name' => 'cover',
'label' => 'Cover image',
'note' => 'Also used in listings',
'fieldNote' => 'Minimum image width: 1500px'
])
@formField('medias', [
'name' => 'slideshow',
'label' => 'Slideshow',
'max' => 5,
'fieldNote' => 'Minimum image width: 1500px'
])
In Model
public $mediasParams = [
'cover' => [
'default' => [
[
'name' => 'default',
'ratio' => 16 / 9,
],
],
'mobile' => [
[
'name' => 'mobile',
'ratio' => 1,
],
],
],
];
Files
@formField('files', [
'name' => 'single_file',
'label' => 'Single file',
'note' => 'Add one file (per language)'
])
@formField('files', [
'name' => 'files',
'label' => 'Files',
'max' => 4,
])
In Model
public $filesParams = ['file_role', ...]; // a list of file roles
Twill Config
return [
'block_editor' => [
'crops' => [
...
],
'files' => ['file_role1', 'file_role2', ...]
]
Datepicker
@formField('date_picker', [
'name' => 'event_date',
'label' => 'Event date',
'minDate' => '2017-09-10 12:00',
'maxDate' => '2017-12-10 12:00'
])
Timepicker
@formField('time_picker', [
'name' => 'event_time',
'label' => 'Event time',
])
Select
@formField('select', [
'name' => 'office',
'label' => 'Office',
'placeholder' => 'Select an office',
'options' => [
[
'value' => 1,
'label' => 'New York'
],
[
'value' => 2,
'label' => 'London'
],
[
'value' => 3,
'label' => 'Berlin'
]
]
])
Select Unpacked
@formField('select', [
'name' => 'discipline',
'label' => 'Discipline',
'unpack' => true,
'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'
],
[
'value' => 'entertainment',
'label' => 'Entertainment'
],
]
])
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'
]
]
])
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();
}
protected $casts = [
'sectors' => 'array'
]
With dynamic selectors
Create a Sectors module
php artisan twill: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.
Multi Select Inline
@formField('multi_select', [
'name' => 'sectors',
'label' => 'Sectors',
'unpack' => false,
'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'
]
]
])
Checkbox
@formField('checkbox', [
'name' => 'featured',
'label' => 'Featured'
])
Multiple Checkboxes
@formField('checkboxes', [
'name' => 'sectors',
'label' => 'Sectors',
'note' => '3 sectors max & at least 1 sector',
'min' => 1,
'max' => 3,
'inline' => true,
'options' => [
[
'value' => 'arts',
'label' => 'Arts & Culture'
],
[
'value' => 'finance',
'label' => 'Banking & Finance'
],
[
'value' => 'civic',
'label' => 'Civic & Public'
],
]
])
Radios
@formField('radios', [
'name' => 'discipline',
'label' => 'Discipline',
'default' => 'civic',
'inline' => true,
'options' => [
[
'value' => 'arts',
'label' => 'Arts & Culture'
],
[
'value' => 'finance',
'label' => 'Banking & Finance'
],
[
'value' => 'civic',
'label' => 'Civic & Public'
],
]
])
Block Editor
@formField('block_editor', [
'blocks' => ['title', 'quote', 'text', 'image', 'grid', 'test', 'publications', 'news']
])
Browser
@formField('browser', [
'moduleName' => 'publications',
'name' => 'publications',
'label' => 'Publications',
'max' => 4,
])
use A17\Twill\Models\Behaviors\HasRelated;
class Article extends Model
{
use HasRelated;
/* ... */
}
class ArticleRepository extends ModuleRepository
{
protected $relatedBrowsers = ['authors'];
}
@extends('twill::layouts.form')
@section('contentFields')
...
@formField('browser', [
'moduleName' => 'authors',
'name' => 'authors',
'label' => 'Authors',
'max' => 4,
])
@stop
Multiple modules as related items
Update ArticleRepository:
class ArticleRepository extends ModuleRepository
{
protected $relatedBrowsers = ['collaborators'];
}
Add the browser field to resources/views/admin/articles/form.blade.php:
@extends('twill::layouts.form')
@section('contentFields')
...
@formField('browser', [
'modules' => [
[
'label' => 'Authors',
'name' => 'authors',
],
[
'label' => 'Editors',
'name' => 'editors',
],
],
'name' => 'collaborators',
'label' => 'Collaborators',
'max' => 4,
])
@stop
Alternatively, you can use manual endpoints instead of module names:
@formField('browser', [
'endpoints' => [
[
'label' => 'Authors',
'value' => '/authors/browser',
],
[
'label' => 'Editors',
'value' => '/editors/browser',
],
],
'name' => 'collaborators',
'label' => 'Collaborators',
'max' => 4,
])
Repeater
@formField('repeater', ['type' => 'video'])
https://twill.io/docs/form-fields/repeater.html#using-repeater-fields
Map
@formField('map', [
'name' => 'location',
'label' => 'Location',
'showMap' => true,
])
Schema::table('posts', function (Blueprint $table) {
...
$table->json('location')->nullable();
...
});
public $casts = [
'location' => 'array',
];
Color
@formField('color', [
'name' => 'main_color',
'label' => 'Main color'
])
Conditional Fields
@formField('radios', [
'name' => 'type',
'label' => 'Article type',
'default' => 'long_form',
'inline' => true,
'options' => [
[
'value' => 'long_form',
'label' => 'Long form article'
],
[
'value' => 'video',
'label' => 'Video article'
]
]
])
@formConnectedFields([
'fieldName' => 'type',
'fieldValues' => 'video',
'renderForBlocks' => true/false # (depending on regular form vs block form)
])
@formField('input', [
'name' => 'video_embed',
'label' => 'Video embed'
])
@endformConnectedFields
@formField('checkbox', [
'name' => 'vertical_article',
'label' => 'Vertical Story'
])
@formConnectedFields([
'fieldName' => 'vertical_article',
'fieldValues' => true,
'renderForBlocks' => true/false # (depending on regular form vs block form)
])
@formField('medias', [
'name' => 'vertical_image',
'label' => 'Vertical Image',
])
@endformConnectedFields
$model->image('cover')
$model->images('cover')
$model->imageObject('cover')
$model->medias()->get()
$model->imageObject('cover')
$model->imageObjects('cover')
\ImageService::getUrl($model->imageObjects('cover')->first()->uuid,["h" => "200"])
$model->imageObjects('cover')->first()->toCmsArray()