Cover of the book Symfony 5: The Fast Track

Symfony 5: The Fast Track is the best book to learn modern Symfony development, from zero to production. +300 pages in full color showing how to combine Symfony with Docker, APIs, queues & async tasks, Webpack, Single-Page Applications, etc.

Buy printed version

15. Field Types

4.x version
Maintained

15. Field Types

15.1. List and Show Actions

There are many field types that can be used in the list and show action :

Fieldtype Description
TemplateRegistry::TYPE_ARRAY display value from an array
TemplateRegistry::TYPE_BOOLEAN display a green or red picture dependant on the boolean value
TemplateRegistry::TYPE_DATE display a formatted date. Accepts the option format
TemplateRegistry::TYPE_TIME display a formatted time. Accepts the options format and timezone
TemplateRegistry::TYPE_DATETIME display a formatted date and time. Accepts the options format and timezone
TemplateRegistry::TYPE_STRING display a text
TemplateRegistry::TYPE_EMAIL display a mailto link. Accepts the options as_string, subject and body
TemplateRegistry::TYPE_TEXTAREA display a textarea
TemplateRegistry::TYPE_TRANS translate the value with a provided catalogue (translation domain) and format (sprintf format) option
TemplateRegistry::TYPE_FLOAT display a number
TemplateRegistry::TYPE_CURRENCY display a number with a provided currency option
TemplateRegistry::TYPE_PERCENT display a percentage
TemplateRegistry::TYPE_CHOICE uses the given value as index for the choices array and displays (and optionally translates) the matching value
TemplateRegistry::TYPE_URL display a link
TemplateRegistry::TYPE_HTML display (and optionally truncate or strip tags from) raw html
TemplateRegistry::TYPE_MANY_TO_MANY used for relational tables
TemplateRegistry::TYPE_MANY_TO_ONE used for relational tables
TemplateRegistry::TYPE_ONE_TO_MANY used for relational tables
TemplateRegistry::TYPE_ONE_TO_ONE used for relational tables

Theses types accept an editable option to edit the value from within the list action. This is currently limited to scalar types (text, integer, url…) and choice types with association field.

Note

If the SonataIntlBundle is installed in the project some template types will be changed to use localized information.

Option for currency type must be an official ISO code, example : EUR for “euros”. List of ISO codes : https://en.wikipedia.org/wiki/List_of_circulating_currencies

In TemplateRegistry::TYPE_DATE, TemplateRegistry::TYPE_TIME and TemplateRegistry::TYPE_DATETIME field types, format pattern must match twig’s date filter specification, available at: https://twig.symfony.com/doc/2.x/filters/date.html

In TemplateRegistry::TYPE_TIME and TemplateRegistry::TYPE_DATETIME field types, timezone syntax must match twig’s date filter specification, available at: https://twig.symfony.com/doc/2.x/filters/date.html and php timezone list: https://www.php.net/manual/en/timezones.php You can use in lists what view-timezone allows on forms, a way to render the date in the user timezone:

protected function configureListFields(ListMapper $listMapper)
{
    $listMapper

        // store date in UTC but display is in the user timezone
        ->add('date', null, [
            'format' => 'Y-m-d H:i',
            'timezone' => 'America/New_York',
        ])
    ;
}

15.1.1. TemplateRegistry::TYPE_ARRAY

You can use the following options:

Option Description
inline If true, the array will be displayed as a single line, the whole array and each array level will be wrapped up with square brackets. If false, the array will be displayed as an unordered list. For the show action, the default value is true and for the list action it’s false.
display Define what should be displayed: keys, values or both. Defaults to ‘both’. Available options are: ‘both’, ‘keys’, ‘values’.
key_translation_domain

This option determines if the keys should be translated and in which translation domain.

The values of this option can be true (use admin translation domain), false (disable translation), null (uses the parent translation domain or the default domain) or a string which represents the exact translation domain to use.

value_translation_domain

This option determines if the values should be translated and in which translation domain.

The values of this option can be true (use admin translation domain), false (disable translation), null (uses the parent translation domain or the default domain) or a string which represents the exact translation domain to use.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
protected function configureListFields(ListMapper $listMapper): void
{
    $listMapper
        ->add('options', TemplateRegistry::TYPE_ARRAY, [
            'inline' => true,
            'display' => 'both',
            'key_translation_domain' => true,
            'value_translation_domain' => null
        ])
    ;
}

15.1.2. TemplateRegistry::TYPE_BOOLEAN

You can use the following options:

Option Description
ajax_hidden Yes/No; ajax_hidden allows to hide list field during an AJAX context.
editable Yes/No; editable allows to edit directly from the list if authorized.
inverse Yes/No; reverses the background color (green for false, red for true).
1
2
3
4
5
6
7
8
9
protected function configureListFields(ListMapper $listMapper)
{
    $listMapper
        ->add('invalid', TemplateRegistry::TYPE_BOOLEAN, [
            'editable' => true,
            'inverse'  => true,
        ])
    ;
}

Note

It is better to prefer non negative notions when possible for boolean values so use the inverse option if you really cannot find a good enough antonym for the name you have.

15.1.3. TemplateRegistry::TYPE_CHOICE

You can use the following options:

Option Description
choices Array of choices.
multiple Determines if choosing multiple options is allowed. Defaults to false.
delimiter Separator of values, if multiple.
catalogue Translation catalogue.
class Class qualified name for editable association field.
required Whether the field is required or not (default true) when the editable option is set to true. If false, an empty placeholder will be added.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
protected function configureListFields(ListMapper $listMapper)
{
    // For the value `prog`, the displayed text is `In progress`. The `App` catalogue will be used to translate `In progress` message.
    $listMapper
        ->add('status', TemplateRegistry::TYPE_CHOICE, [
            'choices' => [
                'prep' => 'Prepared',
                'prog' => 'In progress',
                'done' => 'Done',
            ],
            'catalogue' => 'App',
        ])
    ;
}

The TemplateRegistry::TYPE_CHOICE field type also supports multiple values that can be separated by a delimiter:

protected function configureListFields(ListMapper $listMapper)
{
    // For the value `['r', 'b']`, the displayed text ist `red | blue`.
    $listMapper
        ->add('colors', TemplateRegistry::TYPE_CHOICE, [
            'multiple' => true,
            'delimiter' => ' | ',
            'choices' => [
                'r' => 'red',
                'g' => 'green',
                'b' => 'blue',
            ]
        ])
    ;
}

Note

The default delimiter is a comma ,.

15.1.4. TemplateRegistry::TYPE_URL

Display URL link to external website or controller action.

You can use the following options:

Option Description
hide_protocol remove protocol part from the link text
url URL address (e.g. http://example.com)
attributes array of html tag attributes (e.g. ['target' => '_blank'])
route.name route name (e.g. acme_blog_homepage)
route.parameters array of route parameters (e.g. ['type' => 'example', 'display' => 'full'])
route.absolute boolean value, create absolute or relative url address based on route.name and route.parameters (default false)
route.identifier_parameter_name parameter added to route.parameters, its value is an object identifier (e.g. ‘id’) to create dynamic links based on rendered objects.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
protected function configureListFields(ListMapper $listMapper)
{
    $listMapper
        // Output for value `http://example.com`:
        // `<a href="http://example.com">http://example.com</a>`
        ->add('targetUrl', TemplateRegistry::TYPE_URL)

        // Output for value `http://example.com`:
        // `<a href="http://example.com" target="_blank">example.com</a>`
        ->add('targetUrl', TemplateRegistry::TYPE_URL, [
            'attributes' => ['target' => '_blank']
        ])

        // Output for value `http://example.com`:
        // `<a href="http://example.com">example.com</a>`
        ->add('targetUrl', TemplateRegistry::TYPE_URL, [
            'hide_protocol' => true
        ])

        // Output for value `Homepage of example.com` :
        // `<a href="http://example.com">Homepage of example.com</a>`
        ->add('title', TemplateRegistry::TYPE_URL, [
            'url' => 'http://example.com'
        ])

        // Output for value `Acme Blog Homepage`:
        // `<a href="http://blog.example.com">Acme Blog Homepage</a>`
        ->add('title', TemplateRegistry::TYPE_URL, [
            'route' => [
                'name' => 'acme_blog_homepage',
                'absolute' => true
            ]
        ])

        // Output for value `Sonata is great!` (related object has identifier `123`):
        // `<a href="http://blog.example.com/xml/123">Sonata is great!</a>`
        ->add('title', TemplateRegistry::TYPE_URL, [
            'route' => [
                'name' => 'acme_blog_article',
                'absolute' => true,
                'parameters' => ['format' => 'xml'],
                'identifier_parameter_name' => 'id'
            ]
        ])
    ;
}

Note

Do not use TemplateRegistry::TYPE_URL type with addIdentifier() method, because it will create invalid nested URLs.

15.1.5. TemplateRegistry::TYPE_HTML

Display (and optionally truncate or strip tags from) raw html.

You can use the following options:

Option Description
strip Strip HTML and PHP tags from a string
truncate Truncate a string to length characters beginning from start. Implies strip. Beware of HTML entities. Make sure to configure your HTML editor to disable entities if you want to use truncate. For instance, use config.entities for ckeditor
truncate.length The length to truncate the string to (default 30)
truncate.cut Determines if whole words must be cut (default true)
truncate.ellipsis Ellipsis to be appended to the trimmed string (default ...)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
protected function configureListFields(ListMapper $listMapper)
{
    $listMapper

        // Output for value `<p><strong>Creating a Template for the Field</strong> and form</p>`:
        // `<p><strong>Creating a Template for the Field</strong> and form</p>` (no escaping is done)
        ->add('content', TemplateRegistry::TYPE_HTML)

        // Output for value `<p><strong>Creating a Template for the Field</strong> and form</p>`:
        // `Creating a Template for the Fi...`
        ->add('content', TemplateRegistry::TYPE_HTML, [
            'strip' => true
        ])

        // Output for value `<p><strong>Creating a Template for the Field</strong> and form</p>`:
        // `Creating a Template for...`
        ->add('content', TemplateRegistry::TYPE_HTML, [
            'truncate' => true
        ])

        // Output for value `<p><strong>Creating a Template for the Field</strong> and form</p>`:
        // `Creating a...`
        ->add('content', TemplateRegistry::TYPE_HTML, [
            'truncate' => [
                'length' => 10
            ]
        ])

        // Output for value `<p><strong>Creating a Template for the Field</strong> and form</p>`:
        // `Creating a Template for the Field...`
        ->add('content', TemplateRegistry::TYPE_HTML, [
            'truncate' => [
                'cut' => false
            ]
        ])

        // Output for value `<p><strong>Creating a Template for the Field</strong> and form</p>`:
        // `Creating a Template for the Fi, etc.`
        ->add('content', TemplateRegistry::TYPE_HTML, [
            'truncate' => [
                'ellipsis' => ', etc.'
            ]
        ])

        // Output for value `<p><strong>Creating a Template for the Field</strong> and form</p>`:
        // `Creating a Template for***`
        ->add('content', TemplateRegistry::TYPE_HTML, [
            'truncate' => [
                'length' => 20,
                'cut' => false,
                'ellipsis' => '***'
            ]
        ])
    ;
}

15.2. Create your own field type

Field types are Twig templates that are registered in the configuration section matching your model manager. The example below uses sonata_doctrine_orm_admin.

1
2
3
4
5
6
7
# config/sonata_doctrine_orm_admin.yaml

sonata_doctrine_orm_admin:
    templates:
        types:
            show: # or "list"
                dump: 'fieldtypes/show_dump.html.twig'

Now add a twig file to your templates/ directory. The example below uses @SonataAdmin/CRUD/base_show_field.html.twig to provide the row layout used by the “show” template. Within this base template you can override the field block to rewrite the contents of the field content cell in this row.

1
2
3
4
5
6
7
{# templates/fieldtypes/show_dump.html.twig #}

{% extends '@SonataAdmin/CRUD/base_show_field.html.twig' %}

{% block field %}
    {{ dump(value) }}
{% endblock %}

Take a look at the default templates in @SonataAdmin/Resources/views/CRUD to get an idea of the possibilities when writing field templates.

This work, including the code samples, is licensed under a Creative Commons BY-SA 3.0 license.