Attention
TYPO3 v11 has reached end-of-life as of October 31th 2024 and is no longer being maintained. Use the version switcher on the top left of this page to select documentation for a supported version of TYPO3.
Need more time before upgrading? You can purchase Extended Long Term Support (ELTS) for TYPO3 v11 here: TYPO3 ELTS.
FlexForms
FlexForms can be used to store data within an XML structure inside a single DB column.
More information on this data structure is available in the section T3DataStructure.
FlexForms can be used to configure content elements (CE) or plugins, but they are optional so you can create plugins or content elements without using FlexForms.
Most of the configuration below is the same, whether you are adding configuration
for a plugin or content element. The main difference is how add
is used.
You may want to configure individual plugins or content elements differently, depending on where they are added. The configuration set via the FlexForm mechanism applies to only the content record it has been configured for. The FlexForms configuration for a plugin or CE can be changed by editors in the backend. This gives editors more control over plugin features and what is to be rendered.
Using FlexForms you have all the features of TCA, so it is possible to use input fields, select lists, show options conditionally and more.
Example use cases
The bootstrap_package uses FlexForms to configure rendering options, e.g. a transition interval and transition type (slide, fade) for the carousel content element.
![](../../Images/AutomaticScreenshots/FlexForms/FlexFormCarousel.png)
The carousel content element of EXT:bootstrap_package
Some more extensions that utilize FlexForms are:
- georgringer/news
- blog: This has a very small and basic FlexForm, so it might be a good starting point to look at.
How it works
- In the extension, a configuration schema is defined and attached to one or more content elements or plugins.
- When the CE or plugin is added to a page, it can be configured as defined by the configuration schema.
- The configuration for this content element is automatically saved to
tt_
.content. pi_ flexform - The extension can read current configuration and act according to the configuration.
Tip
The data structure of a FlexForm may change over time. Also, when switching
from one plugin with a FlexForm to another plugin with a FlexForm in an
element, the old values are not removed in the FlexForm field. This
may cause problems and errors. You can avoid this by calling the
CLI command cleanup:
which is
provided by the lowlevel system extension. It
updates all database records which have a FlexForm field and the XML data
does not match the chosen data structure.
Steps to perform (extension developer)
-
Create configuration schema in T3DataStructure format (XML)
Example:
Configuration/
.Flex Forms/ Registration. xml <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <T3DataStructure> <sheets> <sDEF> <ROOT> <TCEforms> <sheetTitle>LLL:EXT:example/Resources/Private/Language/Backend.xlf:settings.registration.title</sheetTitle> </TCEforms> <type>array</type> <el> <!-- Add settings here ... --> <!-- Example setting: input field with name settings.includeCategories --> <settings.includeCategories> <TCEforms> <label>LLL:EXT:example/Resources/Private/Language/Backend.xlf:settings.registration.includeCategories</label> <config> <type>check</type> <default>0</default> <items type="array"> <numIndex index="0" type="array"> <numIndex index="0">LLL:EXT:example/Resources/Private/Language/Backend.xlf:setting.registration.includeCategories.title</numIndex> </numIndex> </items> </config> </TCEforms> </settings.includeCategories> <!-- end of settings --> </el> </ROOT> </sDEF> </sheets> </T3DataStructure>
Copied! -
The configuration schema is attached to one or more plugins
The vendor name is Myvendor, the extension key is example and the plugin name is Registration.
In
Configuration/
add the following:TCA/ Overrides/ tt_ content. php // plugin signature: <extension key without underscores> '_' <plugin name in lowercase> $pluginSignature = 'example_registration'; $GLOBALS['TCA']['tt_content']['types']['list']['subtypes_addlist'][$pluginSignature] = 'pi_flexform'; \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPiFlexFormValue( $pluginSignature, // FlexForm configuration schema file 'FILE:EXT:example/Configuration/FlexForms/Registration.xml' );
Copied!Tip
The plugin signature is used in the database field
tt_
as well, when the tt_content record is saved. If you are confused about how to handle underscores and upper / lowercase, check there to see what your plugin signature is.content. list_ type Also look on the page Naming conventions.
If you are using a content element instead of a plugin, the example will look like this:
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPiFlexFormValue( // 'list_type' does not apply here '*', // FlexForm configuration schema file 'FILE:EXT:example/Configuration/FlexForms/Registration.xml', // ctype 'accordion' );
Copied! -
Access the settings in your extension:
The settings can be read using one of the methods described below, e.g. from an Extbase controller action, from a PHP function (without using the Extbase framework), from TypoScript or from within a Fluid template.
More examples
The definition of the data types and parameters used complies to the column types defined by TCA.
The settings must be added within the <el>
element in the FlexForm
configuration schema file.
Select field
<settings.orderBy>
<TCEforms>
<label>LLL:EXT:example/Resources/Private/Language/Backend.xlf:settings.registration.orderBy</label>
<config>
<type>select</type>
<renderType>selectSingle</renderType>
<items>
<numIndex index="0">
<numIndex index="0">LLL:EXT:example/Resources/Private/Language/Backend.xlf:settings.registration.orderBy.crdate</numIndex>
<numIndex index="1">crdate</numIndex>
</numIndex>
<numIndex index="1">
<numIndex index="0">LLL:EXT:example/Resources/Private/Language/Backend.xlf:settings.registration.orderBy.title</numIndex>
<numIndex index="1">title</numIndex>
</numIndex>
</items>
</config>
</TCEforms>
</settings.orderBy>
See also
- Select fields in TCA reference.
Populate a select
field with a PHP Function (itemsProcFunc)
<settings.orderBy>
<TCEforms>
<label>LLL:EXT:example/Resources/Private/Language/Backend.xlf:settings.registration.orderBy</label>
<config>
<type>select</type>
<itemsProcFunc>MyVendor\Example\Backend\ItemsProcFunc->user_orderBy</itemsProcFunc>
<renderType>selectSingle</renderType>
<items>
<!-- empty by default -->
</items>
</config>
</TCEforms>
</settings.orderBy>
The function user_
populates the select field in
Backend/
:
class ItemsProcFunc
{
/**
* Modifies the select box of orderBy-options.
*
* @param array &$config configuration array
*/
public function user_orderBy(array &$config)
{
// simple and stupid example
// change this to dynamically populate the list!
$config['items'] = [
// label, value
['Timestamp', 'timestamp'],
['Title', 'title']
];
}
// ...
}
How this looks when configuring the plugin:
![](../../Images/ManualScreenshots/FlexForms/FlexFormsItemsProcFunc.png)
See also
- Properties in TCA reference.
Display fields conditionally (displayCond)
Some settings may only make sense, depending on other settings. For example in one setting you define a sorting order (by date, title etc.) and all sort orders except "title" have additional settings. These should only be visible, if sort order "title" was not selected.
You can define conditions using displayCond. This dynamically defines whether a setting should be displayed when the plugin is configured. The conditions may for example depend on one or more other settings in the FlexForm, on database fields of current record or be defined by a user function.
<config>
<type>select</type>
</config>
<!-- Hide field if value of neighbour field "settings.orderBy" on same sheet is not "title" -->
<displayCond>FIELD:settings.orderBy:!=:title</displayCond>
Again, the syntax and available fields and comparison operators is documented in the TCA reference:
See also
- displayCond in TCA Reference
switchableControllerActions
Deprecated since version 10.3
It is no longer considered best practice to use
switchable
in a Flexform. The reasons
for the deprecation and possible alternatives are outlined
in the changelog Deprecation: #89463 - Switchable Controller Actions.
Reload on change
Especially in combination with conditionally displaying settings with displayCond, you may want to trigger a reloading of the form when specific settings are changed. You can do that with:
<onChange>reload</onChange>
<config>
<!-- ... -->
</config>
The on
element is optional and must be placed on the same level as the <config>
element.
How to read FlexForms from an Extbase controller action
The settings can be read using $this->settings
in an
Extbase controller.
$includeCategories = (bool) ($this->settings['includeCategories'] ?? false);
Important
If you wish to access a setting from your controller via
$this->settings
, the name of the setting must be prefixed with settings.
,
so literally settings
directly followed by a dot (.
).
Read FlexForms values in PHP
You can use the Flex
to read the content of a FlexForm field:
use TYPO3\CMS\Core\Service\FlexFormService;
use TYPO3\CMS\Core\Utility\GeneralUtility;
final class NonExtbaseController
{
// Inject FlexFormService
public function __construct(
private readonly FlexFormService $flexFormService,
) {
}
// ...
private function loadFlexForm($flexFormString): array
{
return $this->flexFormService
->convertFlexFormContentToArray($flexFormString);
}
}
Using Flex
the resulting
array can be used conveniently in most use cases:
var_export(
$this->flexFormService->convertFlexFormContentToArray($flexFormString)
);
/* Output:
[
'settings' => [
'singlePid' => 25,
'listPid' => 380,
],
]
*/
The result of General
preserves the internal
structure of the XML FlexForm, and is usually used to modify a FlexForm
string. See section How to modify FlexForms from PHP for an example.
var_export(GeneralUtility::xml2array($flexFormString)));
/* Output:
[
'data' =>
[
'sDEF' =>
[
'lDEF' =>
[
'settings.singlePid' =>['vDEF' => '4',],
'settings.listPid' =>['vDEF' => '',],
],
],
],
];
*/
How to modify FlexForms from PHP
Some situation make it necessary to modify FlexForms via PHP.
In order to convert a FlexForm to a PHP array, preserving the structure,
the xml2array
method in General
can be used to read
the FlexForm data, then the Flex
can be used to write back the
changes.
use \TYPO3\CMS\Core\Utility\GeneralUtility;
use \TYPO3\CMS\Core\Configuration\FlexForm\FlexFormTools;
$flexFormArray = GeneralUtility::xml2array($flexFormString);
$changedFlexFormArray = $this->doSomething($flexFormArray);
$flexFormTools = new FlexFormTools();
$flexFormString = $flexFormTools->flexArray2Xml($changedFlexFormArray, addPrologue: true);
How to access FlexForms From TypoScript
It is possible to read FlexForm properties from TypoScript:
lib.flexformContent = CONTENT
lib.flexformContent {
table = tt_content
select {
pidInList = this
}
renderObj = COA
renderObj {
10 = TEXT
10 {
data = flexform: pi_flexform:settings.categories
}
}
}
The key flexform
is followed by the field which holds the FlexForm data
(pi_
) and the name of the property whose content should be retrieved
(settings.
).
See also
Providing default values for FlexForms attributes
When a new content element with an attached FlexForm is created, the
default values for each FlexForm attribute is fetched from the
<default>
XML attribute within the specification of each
FlexForm attribute. If that is missing, an empty value will be
shown in the backend (FormEngine)
fields.
While you can use page TSconfig's TCAdefaults to modify defaults of usual TCA-based attributes, this is not possible on FlexForms. This is because the values are calculated at an earlier step in the Core workflow, where FlexForm values have not yet been extracted.
How to access FlexForms from Fluid
If you are using an Extbase controller, FlexForm settings can be read from within a Fluid template using
{settings}
. See the note on naming restrictions in How to Read FlexForms From an Extbase Controller Action.
If you defined your FLUIDTEMPLATE
in TypoScript, you can assign single variables like that:
my_content = FLUIDTEMPLATE
my_content {
variables {
categories = TEXT
categories.data = flexform: pi_flexform:categories
}
}
In order to have all FlexForm fields available, you can add a custom DataProcessor.
This example would make your FlexForm data available as Fluid variable {flexform}
:
my_content = FLUIDTEMPLATE
my_content {
dataProcessing {
10 = Your\Ext\DataProcessing\FlexFormProcessor
}
}
namespace Your\Ext\DataProcessing;
use TYPO3\CMS\Core\Service\FlexFormService;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Frontend\ContentObject\DataProcessorInterface;
class FlexFormProcessor implements DataProcessorInterface
{
/**
* @var FlexFormService
*/
protected $flexFormService;
public function __construct(FlexFormService $flexFormService) {
$this->flexFormService = $flexFormService;
}
public function process(
ContentObjectRenderer $cObj,
array $contentObjectConfiguration,
array $processorConfiguration,
array $processedData
): array {
$originalValue = $processedData['data']['pi_flexform'];
if (!is_string($originalValue)) {
return $processedData;
}
$flexformData = $this->flexFormService->convertFlexFormContentToArray($originalValue);
$processedData['flexform'] = $flexformData;
return $processedData;
}
}
See also
Steps to Perform (Editor)
After inserting a plugin, the editor can configure this plugin by switching to the tab "Plugin" or whatever string you defined to replace this.
![](../../Images/ManualScreenshots/FlexForms/FlexformBackend.png)
Credits
Some of the examples were taken from the extensions EXT:news (by Georg Ringer) and EXT:bootstrap_package (by Benjamin Kott).
Further enhancements by the TYPO3 community are welcome!
T3DataStructure
More information on the used data structures within FlexForms can be found in these following chapters: