FlexForm field 

New in version 13.0

Renders a FlexForm element. Essentially, this consists in a hierarchically organized set of fields which will have their values saved into a single field in the database, stored as XML.

The according database field is generated automatically.

The general idea is: There is a data structure that defines which and how single fields should be displayed, re-using all the TCA column type possibilities. The actual values of single fields are then stored in an XML representation within this "flex" field.

Properties of the TCA column type flex 

Changed in version 13.0

The configuration options ds_tableField, ds_pointerField_searchParent_subField and ds_pointerField_searchParent are not handled anymore. Use the Events to replace their logic if needed.

Name Type Scope
boolean Proc.
string Display / Proc.
array
array
array
boolean Display
boolean Display
behaviour
allowLanguageSynchronization
Type
boolean
Default
false
TCA path
$GLOBALS['TCA'][$table]['columns'][$field]['config']['behaviour']['allowLanguageSynchronization']
Scope
Proc.

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.

EXT:my_extension/Configuration/TCA/Overrides/122-tx_myextension_conference-livestream_player.php
<?php

use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;

defined('TYPO3') or die();

ExtensionManagementUtility::addTCAcolumns('tx_myextension_conference', [
  'livestream_player' => [
    'label' => 'my_extension.db:conference.livestream_player',
    'displayCond' => 'FIELD:event_format:IN:online,hybrid',
    'config' => [
      'type' => 'flex',
      // Two settings of the player do not need a file of their own
      'ds' => '
        <T3DataStructure>
          <ROOT>
            <type>array</type>
            <el>
              <autoplay>
                <label>my_extension.db:conference.livestream_player.autoplay</label>
                <config>
                  <type>check</type>
                  <renderType>checkboxToggle</renderType>
                </config>
              </autoplay>
              <muted>
                <label>my_extension.db:conference.livestream_player.muted</label>
                <config>
                  <type>check</type>
                  <renderType>checkboxToggle</renderType>
                </config>
              </muted>
            </el>
          </ROOT>
        </T3DataStructure>
      ',
      // The two toggles hold no text to search for
      'searchable' => false,
      // Translations play the stream like the default language, unless the
      // editors change the settings of a translation
      'behaviour' => [
        'allowLanguageSynchronization' => true,
      ],
    ],
  ],
]);
ExtensionManagementUtility::addToAllTCAtypes(
  'tx_myextension_conference',
  'livestream_player',
  '',
  'after:livestream_password',
);
Copied!
ds
Type
string
TCA path
$GLOBALS['TCA'][$table]['columns'][$field]['config']['ds']
Scope
Display / Proc.

Changed in version 14.0 Breaking: #107047 - Remove pointer field functionality of TCA flex

Multiple entries are no longer supported. Instead use
columnsOverrides.

The changelog entry describes the migration.

This field can either contain a file reference to the file containing the FlexForm's XML ('ds' => 'FILE:EXT:news/Configuration/FlexForm.xml') or contain the XML content directly ('ds' => '<T3DataStructure>...').

Example with XML in external file

A plugin of the extension has its settings in a FlexForm file. The plugin registration sets ds of the field pi_flexform for the record type of the plugin, with columnsOverrides:

EXT:my_extension/Configuration/TCA/Overrides/600-tt_content-conference_list.php
<?php

use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use TYPO3\CMS\Extbase\Utility\ExtensionUtility;

defined('TYPO3') or die();

// A group of its own in the content element wizard and the type select
ExtensionManagementUtility::addTcaSelectItemGroup(
  'tt_content',
  'CType',
  'conference',
  'my_extension.db:tt_content.group.conference',
  'after:plugins',
);

ExtensionUtility::registerPlugin(
  'MyExtension',
  'ConferenceList',
  'my_extension.db:plugin.conferencelist.title',
  'my-extension-conference-list',
  'conference',
  'my_extension.db:plugin.conferencelist.description',
  'FILE:EXT:my_extension/Configuration/FlexForms/ConferenceList.xml',
);

// The plugin lists the upcoming conferences without further settings, so
// a new plugin is saved at once, with its header hidden
$GLOBALS['TCA']['tt_content']['types']['myextension_conferencelist']['creationOptions'] = [
  'defaultValues' => [
    'header_layout' => '100',
  ],
  'saveAndClose' => true,
];
Copied!

The included file:

EXT:my_extension/Configuration/FlexForms/ConferenceList.xml
<T3DataStructure>
  <sheets>
    <sDEF>
      <ROOT>
        <sheetTitle>my_extension.db:plugin.conferencelist.sheet.general</sheetTitle>
        <type>array</type>
        <el>
          <settings.mode>
            <label>my_extension.db:plugin.conferencelist.mode</label>
            <onChange>reload</onChange>
            <config>
              <type>select</type>
              <renderType>selectSingle</renderType>
              <items>
                <numIndex index="0">
                  <label>my_extension.db:plugin.conferencelist.mode.upcoming</label>
                  <value>upcoming</value>
                </numIndex>
                <numIndex index="1">
                  <label>my_extension.db:plugin.conferencelist.mode.past</label>
                  <value>past</value>
                </numIndex>
                <numIndex index="2">
                  <label>my_extension.db:plugin.conferencelist.mode.selected</label>
                  <value>selected</value>
                </numIndex>
              </items>
            </config>
          </settings.mode>
          <settings.conferences>
            <label>my_extension.db:plugin.conferencelist.conferences</label>
            <displayCond>FIELD:settings.mode:=:selected</displayCond>
            <config>
              <type>group</type>
              <allowed>tx_myextension_conference</allowed>
            </config>
          </settings.conferences>
          <settings.categories>
            <label>my_extension.db:plugin.conferencelist.categories</label>
            <config>
              <type>category</type>
            </config>
          </settings.categories>
          <settings.display>
            <label>my_extension.db:plugin.conferencelist.display</label>
            <config>
              <type>check</type>
              <items>
                <numIndex index="0">
                  <label>my_extension.db:plugin.conferencelist.display.logo</label>
                </numIndex>
                <numIndex index="1">
                  <label>my_extension.db:plugin.conferencelist.display.location</label>
                </numIndex>
                <numIndex index="2">
                  <label>my_extension.db:plugin.conferencelist.display.speakers</label>
                </numIndex>
                <numIndex index="3">
                  <label>my_extension.db:plugin.conferencelist.display.date</label>
                </numIndex>
              </items>
              <cols>3</cols>
              <default>15</default>
            </config>
          </settings.display>
          <settings.limit>
            <label>my_extension.db:plugin.conferencelist.limit</label>
            <displayCond>
              <or>
                <value1>FIELD:settings.mode:=:upcoming</value1>
                <value2>FIELD:settings.mode:=:past</value2>
              </or>
            </displayCond>
            <config>
              <type>number</type>
              <default>10</default>
            </config>
          </settings.limit>
          <settings.country>
            <label>my_extension.db:plugin.conferencelist.country</label>
            <config>
              <type>country</type>
              <labelField>localizedName</labelField>
              <size>4</size>
              <prioritizedCountries>
                <numIndex index="0">CH</numIndex>
                <numIndex index="1">DE</numIndex>
                <numIndex index="2">AT</numIndex>
              </prioritizedCountries>
            </config>
          </settings.country>
          <settings.timezone>
            <label>my_extension.db:plugin.conferencelist.timezone</label>
            <config>
              <type>select</type>
              <renderType>selectSingle</renderType>
              <items>
                <numIndex index="0">
                  <label></label>
                  <value></value>
                </numIndex>
              </items>
              <itemsProcessors>
                <numIndex index="100">
                  <class>MyVendor\MyExtension\Backend\ItemsProcessor\TimezoneItemsProcessor</class>
                  <parameters>
                    <regions>Europe</regions>
                  </parameters>
                </numIndex>
              </itemsProcessors>
            </config>
          </settings.timezone>
        </el>
      </ROOT>
    </sDEF>
    <sHighlights>
      <ROOT>
        <sheetTitle>my_extension.db:plugin.conferencelist.sheet.highlights</sheetTitle>
        <sheetDescription>my_extension.db:plugin.conferencelist.sheet.highlights.description</sheetDescription>
        <type>array</type>
        <el>
          <settings.introduction>
            <label>my_extension.db:plugin.conferencelist.introduction</label>
            <config>
              <type>text</type>
              <enableRichtext>1</enableRichtext>
            </config>
          </settings.introduction>
          <settings.highlights>
            <title>my_extension.db:plugin.conferencelist.highlights</title>
            <type>array</type>
            <section>1</section>
            <el>
              <highlight>
                <title>my_extension.db:plugin.conferencelist.highlight</title>
                <type>array</type>
                <el>
                  <title>
                    <label>my_extension.db:plugin.conferencelist.highlight.title</label>
                    <config>
                      <type>input</type>
                    </config>
                  </title>
                  <link>
                    <label>my_extension.db:plugin.conferencelist.highlight.link</label>
                    <config>
                      <type>link</type>
                    </config>
                  </link>
                </el>
              </highlight>
            </el>
          </settings.highlights>
        </el>
      </ROOT>
    </sHighlights>
  </sheets>
</T3DataStructure>
Copied!
Example with XML directly entered

The two settings of the live stream player of a conference are in its TCA:

EXT:my_extension/Configuration/TCA/Overrides/122-tx_myextension_conference-livestream_player.php
<?php

use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;

defined('TYPO3') or die();

ExtensionManagementUtility::addTCAcolumns('tx_myextension_conference', [
  'livestream_player' => [
    'label' => 'my_extension.db:conference.livestream_player',
    'displayCond' => 'FIELD:event_format:IN:online,hybrid',
    'config' => [
      'type' => 'flex',
      // Two settings of the player do not need a file of their own
      'ds' => '
        <T3DataStructure>
          <ROOT>
            <type>array</type>
            <el>
              <autoplay>
                <label>my_extension.db:conference.livestream_player.autoplay</label>
                <config>
                  <type>check</type>
                  <renderType>checkboxToggle</renderType>
                </config>
              </autoplay>
              <muted>
                <label>my_extension.db:conference.livestream_player.muted</label>
                <config>
                  <type>check</type>
                  <renderType>checkboxToggle</renderType>
                </config>
              </muted>
            </el>
          </ROOT>
        </T3DataStructure>
      ',
      // The two toggles hold no text to search for
      'searchable' => false,
      // Translations play the stream like the default language, unless the
      // editors change the settings of a translation
      'behaviour' => [
        'allowLanguageSynchronization' => true,
      ],
    ],
  ],
]);
ExtensionManagementUtility::addToAllTCAtypes(
  'tx_myextension_conference',
  'livestream_player',
  '',
  'after:livestream_password',
);
Copied!

Changed in version 14.0 Breaking: #107047 - Remove pointer field functionality of TCA flex

Option ds_pointerField has been removed. Use ds in combination with columnsOverrides.

The changelog entry describes the migration.

fieldInformation

For details see fieldInformation.

fieldWizard
defaultLanguageDifferences
Type
array
TCA path
$GLOBALS['TCA'][$table]['columns'][$field]['config']['fieldWizard']['defaultLanguageDifferences']

For details see defaultLanguageDifferences.

localizationStateSelector
Type
array
TCA path
$GLOBALS['TCA'][$table]['columns'][$field]['config']['fieldWizard']['localizationStateSelector']

For details see localizationStateSelector.

otherLanguageContent
Type
array
TCA path
$GLOBALS['TCA'][$table]['columns'][$field]['config']['fieldWizard']['otherLanguageContent']

For details see otherLanguageContent.

readOnly
Type
boolean
TCA path
$GLOBALS['TCA'][$table]['columns'][$field]['config']['readOnly']
Scope
Display

Renders the field in a way that the user can see the value but cannot edit it.

searchable
Type
boolean
Default
true
TCA path
$GLOBALS['TCA'][$table]['columns'][$field]['config']['searchable']
Scope
Display

New in version 14.0

TYPO3 now automatically includes all fields of suitable types in backend search operations in the Content > Records module.

This option can be used to explicitly exclude fields from being searchable, instead of having to list them in the now removed option $GLOBALS['TCA'][$table]['ctrl']['searchFields'].

By default, all fields of type flex are considered searchable. To exclude a field from being searchable, set the following in the field's TCA configuration:

EXT:my_extension/Configuration/TCA/Overrides/122-tx_myextension_conference-livestream_player.php
<?php

use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;

defined('TYPO3') or die();

ExtensionManagementUtility::addTCAcolumns('tx_myextension_conference', [
  'livestream_player' => [
    'label' => 'my_extension.db:conference.livestream_player',
    'displayCond' => 'FIELD:event_format:IN:online,hybrid',
    'config' => [
      'type' => 'flex',
      // Two settings of the player do not need a file of their own
      'ds' => '
        <T3DataStructure>
          <ROOT>
            <type>array</type>
            <el>
              <autoplay>
                <label>my_extension.db:conference.livestream_player.autoplay</label>
                <config>
                  <type>check</type>
                  <renderType>checkboxToggle</renderType>
                </config>
              </autoplay>
              <muted>
                <label>my_extension.db:conference.livestream_player.muted</label>
                <config>
                  <type>check</type>
                  <renderType>checkboxToggle</renderType>
                </config>
              </muted>
            </el>
          </ROOT>
        </T3DataStructure>
      ',
      // The two toggles hold no text to search for
      'searchable' => false,
      // Translations play the stream like the default language, unless the
      // editors change the settings of a translation
      'behaviour' => [
        'allowLanguageSynchronization' => true,
      ],
    ],
  ],
]);
ExtensionManagementUtility::addToAllTCAtypes(
  'tx_myextension_conference',
  'livestream_player',
  '',
  'after:livestream_password',
);
Copied!

Defining multiple data structures for different records 

There can be multiple data structures defined in TCA and which one is chosen depends on the configuration and the record . You can use ds or Events to manipulate which data structure should be displayed.

Events to manipulate the FlexForm data structure 

There are appropriate events that allow the manipulation of the data structure lookup logic: