The [‘types’] section plays a crucial role in TCA to specify which fields from the [‘columns’] section
are displayed if editing a table row in FormEngine. At least one type has to be configured before any field
will show up, the default type is
Multiple types can be configured, which one is selected depends on the value of the field specified in [‘ctrl’][‘type’] property. This approach is similar to what is often done with Single Table Inheritance in Object-orientated programming.
The [‘types’] system is powerful and allows differently shaped editing forms re-using fields, having own fields
for specific forms and arranging fields differently on top of a single database table. The
tt_content with all
its different content elements is a good example on what can be done with [‘types’].
The basic [‘types’] structure looks like this:
'types' => [ '0' => [ 'showitem' => 'aField, anotherField', ], 'anotherType' => [ 'showitem' => 'aField, aDifferentField', ], ],
So, the basic array has a key field with type names (here ‘0’, and ‘anotherType’), with a series of possible properties each, most importantly the showitem property.
Let’s take the internal notes (sys_note) as a basic example. The [‘types’] section is configured like this:
'types' => [ '0' => [ 'showitem' => ' --div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:general, category, subject, message, --div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:access, personal ', ], ]
It specifies two tabs: the first one labelled “general” with three fields “category” “subject” and “message”, and the second one labelled “access” with the field “personal”. Only the default type “0” is specified. Opening such a record looks like this:
The power of the “types” configuration becomes clear when you want the form composition of a record to depend on a value from the record. Let’s look at the “tx_examples_dummy” table from the “examples” extension. The “ctrl” section of its TCA contains a “type” property:
'ctrl' => [ 'type' => 'record_type', ... ],
This indicates that the field called “record_type” is to specify the “type” of any given record of the table. Let’s look at how this field is defined in [‘columns’]:
'record_type' => [ 'exclude' => 0, 'label' => 'LLL:EXT:examples/Resources/Private/Language/locallang_db.xlf:tx_examples_dummy.record_type', 'config' => [ 'type' => 'select', 'renderType' => 'selectSingle', 'items' => [ ['LLL:EXT:examples/Resources/Private/Language/locallang_db.xlf:tx_examples_dummy.record_type.0', 0], ['LLL:EXT:examples/Resources/Private/Language/locallang_db.xlf:tx_examples_dummy.record_type.1', 1], ['LLL:EXT:examples/Resources/Private/Language/locallang_db.xlf:tx_examples_dummy.record_type.2', 2], ] ] ],
There’s nothing unusual here. It’s a pretty straightforward select field, with three options. Finally, in the “types” section, we defined what fields should appear and in what order for every value of the “type” field:
'types' => [ '0' => [ 'showitem' => 'hidden, record_type, title, some_date' ], '1' => [ 'showitem' => 'record_type, title' ], '2' => [ 'showitem' => 'title, some_date, hidden, record_type' ], ],
The result if the following display when type “Normal” is chosen:
Changing to type “Short” reloads the form and displays the following:
And finally, type “Weird” also shows all fields, but in a different order:
It is a good idea to give all “types” speaking names, except the default type “0”: In the above example, it would have been better to rename “1” to “short” and “2” to “weird”, both for the [‘types’] array keys and the “select” values to give those types some easy to understand meaning if looking at the array.
- “[+/-][bit-number]” => “[comma-separated list of fields (from the main types-config) excluded]”
- string (field name)
Field name, which holds a value being the integer (bit-mask) for the ‘bitmask_excludelist_bits’ array.
It works much like ‘subtype_value_field’ but excludes fields based on whether a bit from the value field is set. See property bitmask_excludelist_bits.
These two properties are rarely used, but pretty powerful if a ‘type=radio’ or ‘type=check’ field is set as bitmask_value_field.
[+/-] indicates whether the bit [bit-number] is set or not.
'types' => [ 'aType' => [ 'showitem' => 'aField, anotherField, yetAnotherField', 'bitmask_value_field' => 'theSubtypeValueField', 'bitmask_excludelist_bits' => [ '-1' => 'anotherField', // Remove if bit 1 is NOT set '+2' => 'yetAnotherField', // Remove if bit 2 is set ], ], ],
With the above configuration, if field database “theSubtypeValueField” is set to value 5 (binary representation “1 0 1”), the fields “anotherField” (-1 = 0 at bit position 1) and “yetAnotherField” (+2 = 1 at bit position 2) are not displayed, thus leaving only field “aField”. If the value is 1 (binary representation “0 0 1”), fields “aField” and “yetAnotherField” are shown, while “anotherField” is not.
- array (columns fields overrides)
Changed or added [‘columns’] field display definitions.
This allows to change the column definition of a field if a record of this type is edited. Currently, it only affects the display of form fields, but not the data handling.
A typical property that can be changed here is
The core uses this property to override for instance the “bodytext” field config of table “tt_content”: If a record of type “text” is edited, it adds “enableRichtext = 1” to trigger an RTE to the default “bodytext” configuration, and if a type “table” is edited, it adds “renderType = textTable” and “wrap = off” to “bodytext”.
The FormEngine basically merges “columnsOverrides” over the default “columns” field after the record type has been determined.
Example adding “nowrap” to a text type for type “text”
'types' => [ 'text' => [ 'showitem' => 'hidden, myText' 'columnsOverrides' => [ 'myText' => [ 'config' => [ 'wrap' => 'off', ], ], ], ], ... ],
It is not possible to override any properties in “Proc.” scope: The DataHandler does not take “columnsOverrides” into account. Only pure “Display” related properties can be overridden. This especially means that columns config ‘type’ must not be set to a different value.
- string (list of field configuration sets)
Configuration of the displayed order of fields in FormEngine and their tab alignment.
The whole string is a comma
,separated list of tokens. Each token can have keywords separated by semicolon
Each comma separated token is one of the following:
- Name of a field to show. Optionally an alternative label (string or LLL reference) to override the default label from columns section.
Name of a palette to show. The label (string or LLL reference) is optional. If set, it is shown above the single palette fields. The palette name is required and must reference a palette from the palette section.
--palette--;;caching // Show palette "caching" without additional label --palette--;Caching;caching // Show palette "caching" with label "Caching"
- Put all fields after this token onto a new tab and name the tab as given in “tabLabel” (string or LLL reference).
'types' => [ '0' => [ 'showitem' => 'hidden, title, poem,', ], ],
The above example shows three fields of the form. Since no further ‘–div–’ are specified, there would be only one tab. In this case FormEngine will suppress that single tab and just show all specified fields without a tabbing indicator.
'types' => [ '0' => [ 'showitem' => ' hidden, title, poem, --div--;LLL:EXT:examples/locallang_db.xml:tx_examples_haiku.images, image1, image2, ' ], ],
Put three fields on first tab “General” and the two fields “image1” and “image2” on a second tab with the localized name found in “EXT:examples/locallang_db.xml:tx_examples_haiku.images”.
'types' => [ '0' => [ 'showitem' => ' --div--;LLL:EXT:examples/locallang_db.xml:tx_examples_haiku.images, hidden, title, poem, --div--;LLL:EXT:examples/locallang_db.xml:tx_examples_haiku.images, image1, image2, ' ], ],
Similar to the example before, but rename the “General” tab to the string specified in label “LLL:EXT:examples/locallang_db.xml:tx_examples_haiku.images”.
It is good practice to add a comma in excess behind the very last field name as shown in the examples above. The FormEngine code will ignore this, but it helps developers to not forget about a comma when additional fields are added, which can suppress an annoying “Why is my new field not displayed?” bug hunt.
- string (field name)
Field name, which holds a value being a key in the ‘subtypes_excludelist’ array. This allows to add and hide fields found in the types configuration, based on the value of another field in the row.
Example (from typo3/sysext/frontend/Configuration/TCA/tt_content.php):
'subtype_value_field' => 'list_type', 'subtypes_excludelist' => [ '2' => 'layout', '3' => 'layout', '5' => 'layout', ... '21' => 'layout' ],
Above example removes the ‘layout’ field from the ‘types’ definition if field ‘list_type’ is set to ‘2’, ‘3’ and so forth.
A list of fields to add when the “subtype_value_field” matches a key in this array.
- “[value]” => “[comma-separated list of fields which are added]”