Examples 

Simple FlexForm 

The plugin of the conference extension has settings in a FlexForm:

The settings of the conference list plugin

The settings of the conference list plugin

The plugin loads the DataStructure from an external XML file:

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!

Notice the <settings.mode> tag in the DataStructure:

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!

It's clear that the contents of <settings.mode> is a direct reflection of the field configurations we normally set up in the $GLOBALS['TCA'] array.

FlexForm in a plugin 

The data structure for a FlexForm can also be loaded in the pi_flexform field of the tt_content table by adding the following in the TCA overrides of an extension:

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 7th parameter of ExtensionUtility::registerPlugin() registers the FlexForm. TYPO3 shows the field pi_flexform when the record type of the plugin is selected.

Example: FlexForm with two sheets 

This example provides a FlexForm field with two "sheets". Each sheet can contain a separate FlexForm structure. Each sheet can also have a sheet descriptions:

The second sheet of the plugin settings

The second sheet of the plugin settings

The plugin of the conference extension has a second sheet with a description:

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!

Notice how the data of the two sheets are separated.

A flex form field with two flex section containers 

The highlights of the plugin settings

The highlights of the plugin settings

The highlights of the plugin are a section. An editor can add any number of highlights, each with a title and a link:

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: Rich Text Editor in FlexForms 

Creating a RTE in FlexForms is done by enabling enableRichtext content to the tag of the field:

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!