type = ‘inline’

Introduction

Inline-Relational-Record-Editing (IRRE) offers a way of directly editing parent-child-relations in one backend view. New child records are created using AJAX calls to prevent a reload of the complete backend view.

type=’inline’ is a powerful element that allows handling a huge list of relations. This includes simple 1:n and nested 1:n-1:n relations, as well as various m:n relation scenarios with different view aspects and localization setups. Combined with other TCA properties in ‘ctrl’ and ‘types’, the sheer amount of different display variants is amazing.

Be aware that inline has been mostly designed to manage 1:n relations. In those relations one parent record can have multiple children, but one child is connected to only one parent. Children can not be moved from one parent to another.

The exception are m:n relations where a child can be connected via an intermediate table to multiple parents, and the intermediate table can have editable fields on its own, thus attaching additional information to one specific parent-child relation. In the core, the “FAL” / resource handling is an example of that. A parent record (for instance of table “tt_content”) is connected via table “sys_file_reference” to one media resource in “sys_file”. A sys_file record has table “sys_file_metadata” as child record which holds meta information details of the file in question (for instance a description). This information can be overwritten for the specific file resource used in “tt_content” by adding a new description in table “sys_file_reference”. The various inline and field properties like “placeholder” help managing this complex setup in TCA.

Examples

Images

A nested 1:n to 1:n relation

A nested 1:n to 1:n relation

A typical FAL relation

A typical FAL relation

A m:n relation with combination box

A m:n relation with combination box

Simple 1:n relation

This combines a table companies with persons (employees):

'employees' => [
    'exclude' => 1,
    'label' => 'LLL:EXT:myextension/locallang_db.xml:company.employees',
    'config' => [
        'type' => 'inline',
        'foreign_table' => 'person',
        'foreign_field' => 'parentid',
        'foreign_table_field' => 'parenttable',
        'maxitems' => 10,
        'appearance' => [
            'collapseAll' => 1,
            'expandSingle' => 1,
        ],
    ],
],

File Abstraction Layer

Inline-type fields are massively used by the TYPO3 Core in the File Abstraction Layer (FAL).

FAL provides an API for registering an inline-type field with relations to the “sys_file_reference” table containing information related to existing media. Here is how to use it for the “image” field of table “tt_content”:

'image' => [
    'label' => 'LLL:EXT:lang/locallang_general.xlf:LGL.images',
    'config' => \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getFileFieldTCAConfig(
        'image',
        [
            'appearance' => [
               'createNewRelationLinkTitle' => 'LLL:EXT:cms/locallang_ttc.xlf:images.addFileReference'
            ],
            // custom configuration for displaying fields in the overlay/reference table
            // to use the image overlay palette instead of the basic overlay palette
            'overrideChildTca' => [
                'types' => [
                    '0' => [
                        'showitem' => '
                            --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette,
                            --palette--;;filePalette'
                    ],
                    \TYPO3\CMS\Core\Resource\File::FILETYPE_TEXT => [
                        'showitem' => '
                            --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette,
                            --palette--;;filePalette'
                    ],
                ],
            ],
        ],
        $GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext']
    ),
],

The method to call is \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getFileFieldTCAConfig() which takes four parameters. The first one is the name of the field, the second one is an array of configuration options which will be merged with the default configuration. The third one is the list of allowed file types and the fourth one (not used above) the list of disallowed file types. The default field configuration into which the options (second call parameter) are merged looks like:

$fileFieldTCAConfig = [
    'type' => 'inline',
    'foreign_table' => 'sys_file_reference',
    'foreign_field' => 'uid_foreign',
    'foreign_sortby' => 'sorting_foreign',
    'foreign_table_field' => 'tablenames',
    'foreign_match_fields' => [
        'fieldname' => $fieldName
    ],
    'foreign_label' => 'uid_local',
    'foreign_selector' => 'uid_local',
    'overrideChildTca' => [
        'columns' => [
            'uid_local' => [
                'config' => [
                    'appearance' => [
                        'elementBrowserType' => 'file',
                        'elementBrowserAllowed' => $allowedFileExtensions
                    ],
                ],
            ],
        ],
    ],
    'filter' => [
        [
            'userFunc' => 'TYPO3\\CMS\\Core\\Resource\\Filter\\FileExtensionFilter->filterInlineChildren',
            'parameters' => [
                'allowedFileExtensions' => $allowedFileExtensions,
                'disallowedFileExtensions' => $disallowedFileExtensions
            ]
        ]
    ],
    'appearance' => [
        'useSortable' => true,
        'headerThumbnail' => [
            'field' => 'uid_local',
            'width' => '45',
            'height' => '45c',
        ],
        'showPossibleLocalizationRecords' => false,
        'showRemovedLocalizationRecords' => false,
        'showSynchronizationLink' => false,
        'showAllLocalizationLink' => false,

        'enabledControls' => [
            'info' => false,
            'new' => false,
            'dragdrop' => true,
            'sort' => false,
            'hide' => true,
            'delete' => true,
            'localize' => true,
        ],
    ],
];

Attributes on anti-symmetric intermediate table

This example combines companies with persons (employees) using an intermediate table. It is also possible to add attributes to every relation – in this example, an attribute “jobtype” on the “person_company” table is defined. It is also possible to look at the relation from both sides (parent and child):

$GLOBALS['TCA']['person'] = [
    'columns' => [
        'employers' => [
            'label' => 'LLL:EXT:myextension/locallang_db.xml:person.employers',
            'config' => [
                'type' => 'inline',
                'foreign_table' => 'person_company',
                'foreign_field' => 'person',
                'foreign_label' => 'company',
            ],
        ],
    ],
];
$GLOBALS['TCA']['company'] = [
    'columns' => [
        'employees' => [
            'label' => 'LLL:EXT:myextension/locallang_db.xml:company.employees',
            'config' => [
                'type' => 'inline',
                'foreign_table' => 'person_company',
                'foreign_field' => 'company',
                'foreign_label' => 'person',
            ],
        ],
    ],
];
$GLOBALS['TCA']['person_company'] = [
    'columns' => [
        'person' => [
            'label' => 'LLL:EXT:myextension/locallang_db.xml:person_company.person',
            'config' => [
                'type' => 'select',
                'renderType' => 'selectSingle',
                'foreign_table' => 'person',
                'size' => 1,
                'minitems' => 0,
                'maxitems' => 1,
            ],
        ],
        'company' => [
            'label' => 'LLL:EXT:myextension/locallang_db.xml:person_company.company',
            'config' => [
                'type' => 'select',
                'renderType' => 'selectSingle',
                'foreign_table' => 'company',
                'size' => 1,
                'minitems' => 0,
                'maxitems' => 1,
            ],
        ],
        'jobtype' => [
            'label' => 'LLL:EXT:myextension/locallang_db.xml:person_company.jobtype',
            'config' => [
                'type' => 'select',
                'renderType' => 'selectSingle',
                'items' => [
                    ['Project Manager (PM)', '0'],
                    ['Chief Executive Officer (CEO)', '1'],
                    ['Chief Technology Officer (CTO)', '2'],
                ],
                'size' => 1,
                'maxitems' => 1,
            ],
        ],
    ],
];

Attributes on symmetric intermediate table

This example combines two persons with each other – imagine they are married. One person on the first side is the husband, and one person on the other side is the wife (or generally “spouse” in the example below). Symmetric relations combine object of the same with each other and it does not depend, from which side someone is looking to the relation – so the husband knows his wife and the wife also knows her husband.

Sorting could be individually defined for each of the both sides (perhaps this should not be applied to a wife-husband-relationship in real life)

$GLOBALS['TCA']['person'] = [
    'columns' => [
        'employers' => [
            'label' => 'LLL:EXT:myextension/locallang_db.xml:person.employers',
            'config' => [
                'type' => 'inline',
                'foreign_table' => 'person_symmetric',
                'foreign_field' => 'person',
                'foreign_sortby' => 'sorting_person',
                'foreign_label' => 'spouse',
                'symmetric_field' => 'spouse',
                'symmetric_sortby' => 'sorting_spouse',
                'symmetric_label' => 'person',
            ],
        ],
    ],
];
$GLOBALS['TCA']['person_symmetric'] = [
    'columns' => [
        'person' => [
            'label' => 'LLL:EXT:myextension/locallang_db.xml:person_symmetric.person',
            'config' => [
                'type' => 'select',
                'renderType' => 'selectSingle',
                'foreign_table' => 'person',
                'size' => 1,
                'minitems' => 0,
                'maxitems' => 1,
            ],
        ],
        'spouse' => [
            'label' => 'LLL:EXT:myextension/locallang_db.xml:person_symmetric.spouse',
            'config' => [
                'type' => 'select',
                'renderType' => 'selectSingle',
                'foreign_table' => 'person',
                'size' => 1,
                'minitems' => 0,
                'maxitems' => 1,
            ],
        ],
        'someattribute' => [
            'label' => 'LLL:EXT:myextension/locallang_db.xml:person_symmetric.someattribute',
            'config' => [
                'type' => 'input',
            ],
        ],
        'sorting_person' => [
            'config' => [
                'type' => 'passthrough',
            ],
        ],
        'sorting_spouse' => [
            'config' => [
                'type' => 'passthrough',
            ],
        ],
    ],
];

Note

TCAdefaults.<table>.pid = <page id> can be used to define the pid of new child records. Thus, it’s possible to have special storage folders on a per-table-basis. See the TSconfig reference.

Properties renderType default

appearance

Datatype
array
Scope
Display
Description

Has information about the appearance of child-records, namely:

collapseAll (boolean)
Show all child-records collapsed (if false, all are expanded)
expandSingle (boolean)
Show only one child-record expanded each time. If a collapsed record is clicked, the currently open one collapses and the clicked one expands.
newRecordLinkAddTitle (boolean)

Adds the title of the foreign_table to the “New record” link.

false
“Create new”
true
“Create new <title of foreign_table>”, e.g. “Create new address”
newRecordLinkTitle (string or LLL reference)

Overwrites the title of the “New record” link with a localised string. This will work only if newRecordLinkAddTitle is not set to true.

Example:

'newRecordLinkTitle' => 'LLL:EXT:myext/Resources/Private/Language/locallang_db.xlf:my_new_record_label'
levelLinksPosition* (string)
Values: ‘top’ (default), ‘bottom’, ‘both’, ‘none’. Defines where to show the “New record” link in relation to the child records.
useCombination (boolean)
This is only useful on bidirectional relations using an intermediate table with attributes. In a “combination” it is possible to edit the attributes AND the related child record itself. If using a foreign_selector in such a case, the foreign_unique property must be set to the same field as the foreign_selector.
suppressCombinationWarning (boolean)

Suppresses the warning FlashMessage that will be displayed when using useCombination. You can also override the message with your own message using the example below.

Example:

$GLOBALS['TCA']['tx_demo_domain_model_demoinline']['columns']['irre_records']['config'] = [
    'appearance' => [
       'overwriteCombinationWarningMessage' => 'LLL:EXT:demo/Resources/Private/Language/locallang_db.xlf:tx_demo_domain_model_demoinline.irre_records.useCombinationWarning',
       'useCombination' => TRUE
    ],
],
useSortable (boolean)
Activate drag & drop.
showPossibleLocalizationRecords (boolean)
Show unlocalized records which are in the original language, but not yet localized.
showRemovedLocalizationRecords (boolean)
Show records which were once localized but do not exist in the original language anymore.
showAllLocalizationLink (boolean)
Defines whether to show the “localize all records” link to fetch untranslated records from the original language.
showSynchronizationLink (boolean)
Defines whether to show a “synchronize” link to update to a 1:1 translation with the original language.
enabledControls (array)
Associative array with the keys ‘info’, ‘new’, ‘dragdrop’, ‘sort’, ‘hide’, ‘delete’, ‘localize’. If the accordant values are set to a boolean value (true or false), the control is shown or hidden in the header of each record.
showPossibleRecordsSelector (boolean)
Can be used to hide the foreign record selector from the interface, even if you have a foreign_selector configured. This can be used to keep the technical functionality of the foreign_selector but is useful if you want to replace it with your own implementation using a custom control, see customControls.
headerThumbnail (boolean)
Defines whether a thumbnail should be rendered in the inline elements’ header. This is used by the File Abstraction Layer to render a preview of the related image.
fileUploadAllowed (boolean)

Defines whether the button “Select & upload file” should be rendered. This can be used for file fields to directly upload files and create a reference to the file. The button is limited to file fields using File Abstraction Layer. It will only appear to backend users which have write access to the user upload folder. By default this folder is fileadmin/user_upload but it can be changed in User TSconfig using options.defaultUploadFolder. See the TSconfig reference.

The button is shown by default unless this option is set to false.

elementBrowserEnabled (boolean)
Hides or displays the element browser button in inline records
elementBrowserAllowed (string)
Sets the list of allowed element types, e.g. file extensions for file fields. For file fields this also affects whether the “Add media by URL” button is shown if online media file extensions (e.g. youtube or vimeo) are included.

autoSizeMax

Datatype
integer
Scope
Display
Description

Only useful in combination with foreign_selector.

If set, then the height of multiple-item selector boxes (maxitem > 1) will automatically be adjusted to the number of selected elements, however never less than “size” and never larger than the integer value of “autoSizeMax” itself (takes precedence over “size”). So “autoSizeMax” is the maximum height the selector can ever reach.

behaviour

Datatype
array
Scope
Proc.
Description
The behaviour array contains various sub properties to specify processing options like localization overlay behaviour and children behaviour for relation types. Available properties vary by type and renderType combination.

allowLanguageSynchronization

Datatype
boolean
Scope
Proc.
Description
Allows an editor to select in a localized record whether the value is copied over from default or source language record, or if the field has an own value in the localization. If set to true and if the table supports localization and if a localized record is edited, this setting enables FieldWizard LocalizationStateSelector: Two or three radio buttons shown below the field input. The state of this is stored in a json encoded array in the database table called l10n_state. It tells the DataHandler which fields of the localization records should be kept in sync if the underlying default or source record changes.
Default
false

disableMovingChildrenWithParent

Datatype
boolean
Scope
Proc.
Description

Default false. Disables that child records get moved along with their parent records. Usually if in a parent-child relation a parent record is moved to a different page (eg. via cut+paste from clipboard), the children are relocated along with the parent. This flag disables the child move.

This property can be especially useful if all child records should be gathered in one storage folder and their parents are spread out at different places in the page tree. In combination with the Tsconfig setting TCAdefaults.<table>.pid = <page id> children can be forced to be created in this folder and stay there.

enableCascadingDelete

Datatype
boolean
Scope
Proc.
Description
Default true. Usually in inline relations, if a parent is deleted, all children are deleted along with the parent. This flag can be used to disable that cascading delete. Example usage: A frontend user (parent) has assigned invoices (children). If a frontend user is deleted, it could be useful to keep the invoices.

customControls

Datatype
array
Scope
Display
Description

Numerical array containing definitions of custom header controls for IRRE fields. This makes it possible to create special controls by calling user-defined functions (userFuncs). Each item in the array item must be an array itself, with at least on key “userFunc” pointing to the user function to call.

The userFunc string is defined as usual in TYPO3 as [‘class’]->[‘method’], e.g.

\Vendor\Extension\MyClass::class . '->myUserFuncMethod'

For more details, see the implementation in TYPO3\\CMS\\Backend\\Form\\Container\\InlineControlContainer and search for “customControls”.

filter

Datatype
array
Scope
Display / Proc.
Description

Possibility to define user functions to filter out child items.

This is useful in special scenarios when used in conjunction with a foreign_selector where only certain foreign records are allowed to be related to.

For further documentation on this feature, see the “filter” documentation under TYPE: “group”.

foreign_default_sortby

Datatype
string
Scope
Display
Description
If a field name for foreign_sortby is defined, then this is ignored. Otherwise, this is used as the “ORDER BY” statement to sort the records in the table when listed.

foreign_field

Datatype
string
Scope
Display / Proc.
Description
The foreign_field is the field of the child record pointing to the parent record. This defines where to store the uid of the parent record.

foreign_label

Datatype
string
Scope
Display / Proc.
Description
If set, it overrides the label set in $GLOBALS['TCA'][<foreign_table>]['ctrl']['label'] for the inline-view.

foreign_match_fields

Datatype
array
Scope
Proc.
Description

Array of field-value pairs to both insert and match against when writing/reading IRRE relations. Using the match fields, it is possible to re-use the same child table in more than one field of the parent table by using a match field with different values for each of the use cases.

Imagine you have a parent table called “company” and a child table called “persons”. Now, if you want the company table to have two fields of type “inline”, one called “employees” and one called “customers”, both containing “persons”. Then you could use a (hidden) field called “role” on the child (person) table to keep them apart. The match TCA configuration of the parent table would then look like this:

$GLOBALS['TCA']['ty_myext_company'] = [
    'columns' => [
        'employees' => [
            'config' => [
                'type' => 'inline',
                'foreign_table' => 'ty_myext_person',
                'foreign_field' => 'company',
                'foreign_match_fields' => [
                    'role' => 'employee',
                ],
            ],
        ],
        'customers' => [
            'config' => [
                'type' => 'inline',
                'foreign_table' => 'ty_myext_person',
                'foreign_field' => 'company',
                'foreign_match_fields' => [
                    'role' => 'customer',
                ],
            ],
        ],
    ],
];

If the match field is made editable, for instance as a select drop-down of two values, the the relation would switch between the two parent fields after change an save. Imagine a user record having “open” and “closed” issues assigned, both pointing to the same table. The user then switches the status of an issue from “open” to “closed”. On save, the issue would “move over” to the “closed” section in his view.

foreign_selector

Datatype
string
Scope
Display / Proc.
Description
A selector is used to show all possible child records that could be used to create a relation with the parent record. It will be rendered as a multi-select-box. On clicking on an item inside the selector a new relation is created. The foreign_selector points to a field of the foreign_table that is responsible for providing a selector-box – this field on the foreign_table usually is of type select and also has a foreign_table defined.

foreign_sortby

Datatype
string
Scope
Display / Proc.
Description
Define a field on the child record (or on the intermediate table) that stores the manual sorting information. It is possible to have a different sorting, depending from which side of the relation we look at parent or child. This property requires that the foreign_field approach is used.

Important

If you use the table only as an inline element, do not put the sortby field in the ctrl section, otherwise TYPO3 CMS will sort the entire table with every update. For example, if you have 10000 records, each with 4 inline elements, TYPO3 CMS will sort 40000 records even if only 4 must be sorted.

foreign_table

Datatype
string (table name)
Scope
Display / Proc.
Description

Required

The table name of the child records is defined here. The table must be configured in $GLOBALS['TCA'].

foreign_table_field

Datatype
string
Scope
Display / Proc.
Description
The foreign_table_field is the field of the child record pointing to the parent record. This defines where to store the table name of the parent record. On setting this configuration key together with foreign_field, the child record knows what its parent record is – so the child record could also be used on other parent tables.This issue is also known as “weak entity”. Do not confuse with foreign_table or foreign_field. It has its own behavior.

foreign_unique

Datatype
string
Scope
Display / Proc.
Description

Field which must be unique for all children of a parent record.

Example: Say you have two tables, products, your parent table, and prices, your child table (products) can have multiple prices. The prices table has a field called customer_group, which is a selector box. Now you want to be able to specify prices for each customer group when you edit a product, but of course you don’t want to specify contradicting prices for one product (i.e. two different prices for the same customer_group). That’s why you would set foreign_unique to the field name “customer_group”, to prevent that two prices for the same customer group can be created for one product.

maxitems

Datatype
integer > 0
Scope

Maximum number of child items. Defaults to a high value. JavaScript record validation prevents the record from being saved if the limit is not satisfied.

Note

Property maxitems is ignored with type='select' and renderType='selectSingle'.

Description
Display / Proc.

minitems

Datatype
integer > 0
Scope
Display
Description
Minimum number of child items. Defaults to 0. JavaScript record validation prevents the record from being saved if the limit is not satisfied.

MM

Datatype
string (table name)
Scope
Proc.
Description

Means that the relation to the records of foreign_table is done with a M-M relation with a third “intermediate” table.

That table typically has three columns:

uid_local, uid_foreign
Storing uids of both sides. If done right, this is reflected in the table name - tx_foo_local_foreign_mm
sorting
is a required field used for ordering the items.
further fields
May exist, in particular if MM_match_fields is involved in the set up.

The field which is configured as “inline” is not used for data-storage any more but rather it’s set to the number of records in the relation on each update, so the field should be an integer.

Warning

Copying with MM relations will not create a copy of the value. Thus copying the record Org with Org->orgA and Org->orgB as New results in New->orgA and New->orgB instead of New->newA and New->newB. Deleting the relation New->orgA will result in a broken relation Org->orgA.

MM_match_fields

Datatype
array
Scope
Display / Proc.
Description
Array of field=>value pairs to both insert and match against when writing/reading MM relations.

overrideChildTca

Datatype
array
Scope
Display
Description

This property can be used to override certain aspects of the child’s TCA if that child record is opened inline of the given parent. Display related TCA properties of the child table can be overridden in types and columns section.

This example overrides the crop variants in a configured fal relation:

'assets' => [
    'config' => [
        'overrideChildTca' => [
            'columns' => [
                'crop' => [
                    'config' => [
                        'cropVariants' => [
                            'default' => [
                                'disabled' => true,
                            ],
                            'mobile' => [
                                'title' => 'LLL:EXT:ext_key/Resources/Private/Language/locallang.xlf:imageManipulation.mobile',
                                'cropArea' => [
                                    'x' => 0.1,
                                    'y' => 0.1,
                                    'width' => 0.8,
                                    'height' => 0.8,
                                ],
                                'allowedAspectRatios' => [
                                    '4:3' => [
                                        'title' => 'LLL:EXT:lang/Resources/Private/Language/locallang_wizards.xlf:imwizard.ratio.4_3',
                                        'value' => 4 / 3
                                    ],
                                    'NaN' => [
                                        'title' => 'LLL:EXT:lang/Resources/Private/Language/locallang_wizards.xlf:imwizard.ratio.free',
                                        'value' => 0.0
                                    ],
                                ],
                            ],
                        ],
                    ],
                ],
            ],
        ],
    ],
],

This example overrides the showitem field of the child table TCA:

'anInlineField' => [
    'config' => [
        'type' => 'inline',
        'overrideChildTca' => [
            'types' => [
                'aForeignType' => [
                    'showitem' => 'aChildField',
                ],
            ],
        ],
    ],
],

This overrides the default columns property of a child field in an inline relation from within the parent if a new child is created:

'anInlineField' => [
    'config' => [
        'type' => 'inline',
        'overrideChildTca' => [
            'columns' => [
                'CType' => [
                    'config' => [
                        'default' => 'image',
                    ],
                ],
            ],
        ],
    ],
];

This overrides the foreign_selector field target field config, defined in the foreign_selector property. This is used in FAL inline relations:

'anInlineField' => [
    'config' => [
        'type' => 'inline',
        'foreign_selector' => 'uid_local',
        'overrideChildTca' => [
            'columns' => [
                'uid_local' => [
                    'config' => [
                        'appearance' => [
                            'elementBrowserType' => 'file',
                            'elementBrowserAllowed' => $allowedFileExtensions
                        ],
                    ],
                ],
            ],
        ],
    ],
],

Note

It is allowed to use this property within the columnsOverrides property of an inline parent in the ['types'] section.

size

Datatype
integer
Scope
Display
Description

Only useful in combination with foreign_selector.

If set to 1 (default), the combination box is a select drop-down, else a select box of given size.

symmetric_field

Datatype
string
Scope
Display / Proc.
Description
This works like foreign_field, but in case of using bidirectional symmetric relations. symmetric_field defines in which field on the foreign_table the uid of the “other” parent is stored.

symmetric_label

Datatype
string
Scope
Display / Proc.
Description
If set, it overrides the label set in $GLOBALS['TCA'][<foreign_table>]['ctrl']['label'] for the inline-view and only if looking to a symmetric relation from the “other” side.

symmetric_sortby

Datatype
string
Scope
Display / Proc.
Description
This works like foreign_sortby, but in case of using bidirectional symmetric relations. Each side of a symmetric relation could have its own sorting, so symmetric_sortby defines a field on the foreign_table where the sorting of the “other” side is stored. This property requires that the foreign_field approach is used.