5. Form field definition
5.1. Example
namespace Sonata\NewsBundle\Admin;
use Sonata\AdminBundle\Admin\AbstractAdmin;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Form\Type\ModelListType;
use Sonata\Form\Validator\ErrorElement;
final class PostAdmin extends AbstractAdmin
{
protected function configureFormFields(FormMapper $form): void
{
$form
->add('author', ModelListType::class, [])
->add('enabled')
// you can define help messages using Symfony help option
->add('title', null, ['help' => 'help_post_title'])
->add('abstract', null, ['required' => false])
->add('content');
}
}
Note
By default, the form framework always sets required=true
for each field.
This can be an issue for HTML5 browsers as they provide client-side validation.
5.2. Short Object Placeholder
When using Many-to-One or One-to-One relations with Sonata Type fields,a short object description is used to represent the target object. If no object is selected, a No selection placeholder will be used. If you want to customize this placeholder, you can use the corresponding option in the form field definition:
namespace Sonata\NewsBundle\Admin;
use Sonata\AdminBundle\Admin\AbstractAdmin;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Form\Type\ModelListType;
final class PostAdmin extends AbstractAdmin
{
protected function configureFormFields(FormMapper $form): void
{
$form
->with('General')
->add('enabled', null, ['required' => false])
->add('author', ModelListType::class, [], [
'placeholder' => 'No author selected',
]);
}
}
This placeholder is translated using the SonataAdminBundle
catalog.
5.3. Advanced usage: File management
If you want to use custom types from the Form framework you must use the addType
method:
namespace Sonata\MediaBundle\Admin;
use Sonata\AdminBundle\Admin\AbstractAdmin;
use Sonata\AdminBundle\Form\FormMapper;
final class MediaAdmin extends AbstractAdmin
{
protected function configureFormFields(FormMapper $form): void
{
$form
->add('name', null, ['required' => false])
->add('enabled', null, ['required' => false])
->add('authorName', null, ['required' => false])
->add('cdnIsFlushable', null, ['required' => false])
->add('description', null, ['required' => false])
->add('copyright', null, ['required' => false])
->add('binaryContent', 'file', ['required' => false]);
}
}
Note
The add
method uses the information provided by the model definition.
Note
By setting type=false
in the file definition, the Form framework will provide an instance of
UploadedFile
for the Media::setBinaryContent
method. Otherwise, the full path will be provided.
5.4. Advanced usage: Many-to-one
If you have many Post
linked to one User
, then the Post
form should display a User
field.
The AdminBundle provides 2 options:
Sonata\AdminBundle\Form\Type\ModelType
: theUser
list is set in a select widget with an Add button to create a newUser
,Sonata\AdminBundle\Form\Type\ModelListType
: theUser
list is set in a model where you can search, select and delete aUser
.
The following example shows both types in action:
namespace Sonata\NewsBundle\Admin;
use Sonata\AdminBundle\Admin\AbstractAdmin;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Form\Type\ModelListType;
use Sonata\AdminBundle\Form\Type\ModelType;
final class PostAdmin extends AbstractAdmin
{
protected function configureFormFields(FormMapper $form): void
{
$form
->with('General')
->add('enabled', null, ['required' => false])
->add('author', ModelListType::class, [
'btn_add' => 'Add author', //Specify a custom label
'btn_list' => 'button.list', //which will be translated
'btn_delete' => false, //or hide the button.
'btn_edit' => 'Edit', //Hide add and show edit button when value is set
'btn_catalogue' => 'SonataNewsBundle', //Custom translation domain for buttons
], [
'placeholder' => 'No author selected',
])
->add('title')
->add('abstract')
->add('content')
->end()
->with('Tags')
->add('tags', ModelType::class, ['expanded' => true])
->end()
->with('Options', ['collapsed' => true])
->add('commentsCloseAt')
->add('commentsEnabled', null, ['required' => false])
->add('commentsDefaultStatus', 'choice', [
'choices' => Comment::getStatusList()
])
->end();
}
}
5.5. Advanced Usage: One-to-many
Let’s say you have a Gallery
that links to some Media
.
You can easily add a new Media
row by defining one of these options:
edit
:inline|standard
, the inline mode allows you to add new rows,inline
:table|standard
, the fields are displayed into table,sortable
: if the model has a position field, you can enable a drag and drop sortable effect by settingsortable=field_name
.limit
:<an integer>
if defined, limits the number of elements that can be added, after which the “Add new” button will not be displayed
The following example shows the CollectionType
in action:
namespace Sonata\MediaBundle\Admin;
use Sonata\AdminBundle\Admin\AbstractAdmin;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\Form\Type\CollectionType;
final class GalleryAdmin extends AbstractAdmin
{
protected function configureFormFields(FormMapper $form): void
{
$form
->add('code')
->add('enabled')
->add('name')
->add('defaultFormat')
->add('galleryHasMedias', CollectionType::class, [
'by_reference' => false,
],
[
'edit' => 'inline',
'inline' => 'table',
'sortable' => 'position',
'limit' => 3,
]);
}
}
Note
You have to define the setMedias
method into your Gallery
class and manually attach each media
to the current gallery
and define cascading persistence for the relationship from media to gallery.
By default, position row will be rendered. If you want to hide it, you will need to alter child admin class and add hidden position field. Use code like:
protected function configureFormFields(FormMapper $form): void
{
$form
->add('position', 'hidden', [
'attr' => ['hidden' => true]
]);
}