Core API

4.2.14. ['columns'][fieldname]['config'] / TYPE: "flex"

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

Key

Datatype

Description

type

string

[Must be set to "flex"]

ds_pointerField

string

Fieldname in the record which points to the field where the key for "ds" is found

ds

string

Data Structure(s) defined in an array.

 

Each key is a value that can be pointed to by "ds_pointerField". Default key is "default" which is what you should use if you do not have a "ds_pointerField" value of course.

 

For each value in the array there are two options:

  1. Either enter XML directly

  2. Make a reference to an external XML file

 

Example with XML directly entered:

 

  'config' => Array (
      'type' => 'flex',
      'ds_pointerField' => 'list_type',
      'ds' => array(
          'default' => '
              <T3DataStructure>
                <ROOT>
                  <type>array</type>
                  <el>
                    <xmlTitle>
                      <TCEforms>
                          <label>The Title:</label>
                          <config>
                              <type>input</type>
                              <size>48</size>
                          </config>
                      </TCEforms>
                    </xmlTitle>
                  </el>
                </ROOT>
              </T3DataStructure>
          ',
      )
  )

Example with XML in external file:

(File reference is relative)

  'config' => Array (
      'type' => 'flex',
      'ds_pointerField' => 'list_type',
      'ds' => array(
          'default' => 'FILE:EXT:mininews/flexform_ds.xml',
      )
  )

 

ds_tableField

string

Contains the value "[table]:[fieldname]" from which to fetch Data Structure XML.

 

"ds_pointerField" is in this case the pointer which should contain the uid of a record from that table.

 

This is used by TemplaVoila extension for instance where a field in the tt_content table points to a TemplaVoila Data Structure record:

 

  'tx_templavoila_flex' => Array (        
      'exclude' => 1,
      'label' => '...',
      'displayCond' => 'FIELD:tx_templavoila_ds:REQ:true',
      'config' => Array (
          'type' => 'flex',    
          'ds_pointerField' => 'tx_templavoila_ds',
          'ds_tableField' => 'tx_templavoila_datastructure:dataprot',
      )
  ),

ds_pointerField_searchParent

string

Used to search for Data Structure recursively back in the table assuming that the table is a tree table. This value points to the "pid" field.

See "templavoila" for example - uses this for the Page Template.

ds_pointerField_searchParent_subField

string

Points to a field in the "rootline" which may contain a pointer to the "next-level" template.

See "templavoila" for example - uses this for the Page Template.

 

Pointing to a Data Structure

Basically the configuration for a FlexForm field is all about pointing to the Data Structure which will contain form rendering information in the application specific tag "<TCEforms>".

For general information about the backbone of a Data Structure, please see the <T3DataStructure> chapter in the Data Formats section.

FlexForm facts

FlexForms create a form-in-a-form. The content coming from this form is still stored in the associated database field - but as an XML structure (stored by t3lib_div::array2xml())!

The "TCA" information needed to generate the FlexForm fields are found inside a <T3DataStructure> XML document. When you configure a FlexForm field in a Data Structure (DS) you can use basically all column types documented here for TCA. The limitations are:

  1. "unique" and "uniqueInPid" evaluation is not available

  2. You cannot nest FlexForm configurations inside of FlexForms.

  3. Charset follows that of the current backend (that is "forceCharset" or the backend users language selection)

<T3DataStructure> extensions for "<TCEforms>"

For FlexForms the DS is extended with a tag, "<TCEforms>" which define all settings specific to the FlexForms usage.

Also a few meta tag features are used.

Sometimes it may be necessary to reload flexform if content of the field in the flexform is changed. This is accomplished by adding "<onChange>reload</onChange>" inside <TCEforms>. A typical example for that is a field that defines operational modes for an extension. When the mode changes, a flexform may need to show a new set of fields. By combining the <onChange> tag for mode fields with <displayCond> tag for other fields, it is possible to create truly dynamic flexforms.

Notice that changing the mode does not delete hidden field values of the flexform. Always use the "mode" field to determine which parameters to use.

The tables below document the extension elements:

 

"Array" Elements:

Element

Description

Child elements

<meta>

Can contain application specific meta settings. For FlexForms this means a definition of how languages are handled in the form.

<langChildren>

<langDisable>

<[application tag]>

In this case the application tag is "<TCEforms>"

A direct reflection of a ['columns']['fieldname']['config'] PHP array configuring a field in TCA. As XML this is expressed by array2xml()'s output. See example below.

<ROOT><TCEforms>

For <ROOT> elements in the DS you can add application specific information about the sheet that the <ROOT> element represents.

<sheetTitle>

<sheetDescription>

<sheetShortDescr>

 

"Value" Elements:

Element

Format

Description

<langDisable>

Boolean, 0/1

If set, then handling of localizations is disabled. Otherwise FlexForms will allow editing of additional languages than the default according to "sys_languages" table contents.

The language you can select from is the language configured in "sys_languages" but they must have ISO country codes set - see example below.

<langChildren>

Boolean, 0/1

If set, then localizations are bound to the default values 1-1 ("value" level). Otherwise localizations are handled on "structure level"

<sheetTitle>

string

Specifies the title of the sheet. Language splitted.

<sheetDescription>

string

Specifies a description for the sheet shown in the flexform. Language splitted.

<sheetShortDescr>

string

Specifies a short description of the sheet used in the tab-menu. Language splitted.

 

Sheets and FlexForms

FlexForms always resolve sheet definitions in a Data Structure. If only one sheet is defined that must be the "sDEF" sheet (default). In that case no tab-menu for sheets will appear (see examples below).

FlexForm data format, <T3FlexForms>

When saving FlexForm elements the content is stored as XML using t3lib_div::array2xml() to convert the internal PHP array to XML format. The structure is as follows:

"Array" Elements:

Element

Description

Child elements

<T3FlexForms>

Document tag

<meta>

<data>

<meta>

Meta data for the content. For instance information about which sheet is active etc.

<currentSheetId>

<currentLangId>

<data>

Contains the data; sheets, language sections, field and values

<sheet>

<sheet>

Contains the data for each sheet in the form. If there are no sheets, the default sheet "<sDEF>" is always used.

<sDEF>

<s_[sheet keys]>

<sDEF>

<[sheet keys]>

For each sheet it contains elements for each language. If <meta><langChildren> is false then all languages are stored on this level, otherwise only the <lDEF> tag is used.

<lDEF>

<l[ISO language code]>

<lDEF>

<[language keys]>

For each language the fields in the form will be available on this level.

<[fieldname]>

<[fieldname]>

For each fieldname there is at least one element with the value, <vDEF>. If <meta><langChildren> is true then there will be a <v*> tag for each language holding localized values.

<vDEF>

<v[ISO language code]>

<currentLangId>

Numerical array of language ISO codes + "DEF" for default which are currently displayed for editing.

<n[0-x]>

 

"Value" Elements:

Element

Format

Description

<vDEF>

<v[ISO language code]>

string

Content of the field in default or localized versions

<currentSheetId>

string

Points to the currently shown sheet in the DS.

 

For syntax highlighted example, see below.

Example: Simple FlexForm

The extension "mininews"  displays a FlexForm in the Plugin type content element. The form displays a template selector box:

 


The DS used to render this field is found in the file "flexform_ds.xml" inside of the "mininews" extension. Notice the <TCEforms> tags:

 

  <T3DataStructure>
          <meta>
                  <langDisable>1</langDisable>
          </meta>
    <ROOT>
      <type>array</type>
      <el>
        <field_templateObject>
                  <TCEforms>
                          <label>LLL:EXT:mininews/locallang_db.php:tt_content.pi_flexform.select_template</label>

                          <config>
                                  <type>select</type>
                                  <items>
                                          <numIndex index="0">
                                                  <numIndex index="0"></numIndex>
                                                  <numIndex index="1">0</numIndex>
                                          </numIndex>
                                  </items>
                                  <foreign_table>tx_templavoila_tmplobj</foreign_table>
                                  <foreign_table_where>
                                          AND tx_templavoila_tmplobj.pid=###STORAGE_PID###
                                          AND tx_templavoila_tmplobj.datastructure="EXT:mininews/template_datastructure.xml"
                                          AND tx_templavoila_tmplobj.parent=0
                                          ORDER BY tx_templavoila_tmplobj.title
                                  </foreign_table_where>
                                  <size>1</size>
                                  <minitems>0</minitems>
                                  <maxitems>1</maxitems>
                          </config>
                  </TCEforms>
        </field_templateObject>
      </el>
    </ROOT>
  </T3DataStructure>

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

 

To configure the FlexForm field to use this Data Structure, the "mininews" extension simply includes this in the ext_tables.php file:

 

     1: $TCA['tt_content']['types']['list']['subtypes_addlist'][$_EXTKEY.'_pi1']='pi_flexform';
     2: t3lib_extMgm::addPiFlexFormValue($_EXTKEY.'_pi1', 'FILE:EXT:mininews/flexform_ds.xml');

In line 1 the tt_content field "pi_flexform" is added to the display of fields when the Plugin type is selected and set on "mininews_pi1"

In line 2 the DS xml file is configured to be the source of the FlexForm DS used.

If we browse the definition for the "pi_flexform" field in "tt_content" we will see this configuration:

 


As you can see two extension plugins, "newloginbox_pi1" and "mininews_pi1" has added pointers to their Data Structures.

Example: FlexForm with two sheets

In this example we create a flexform field with two "sheets". Each sheet can contain a separate FlexForm structure.

 

  ....['config'] = array(
      'type' => 'flex',
      'ds' => array(
          'default' => '
   
   
  <T3DataStructure>
    <sheets>
          <sDEF>
            <ROOT>
                  <TCEforms>
                          <sheetTitle>Default sheet</sheetTitle>
                  </TCEforms>
              <type>array</type>
              <el>
                <header>
                          <TCEforms>
                                  <label>Header</label>
                                  <config>
                                          <type>input</type>
                                          <size>30</size>
                                  </config>
                          </TCEforms>
                </header>
                <message>
                          <TCEforms>
                                  <label>Message:</label>
                                  <config>
                                          <type>text</type>
                                          <cols>30</cols>
                                          <rows>5</rows>
                                  </config>
                          </TCEforms>
                </message>
              </el>
            </ROOT>
      </sDEF>
      <s_welcome>
            <ROOT>
                  <TCEforms>
                          <sheetTitle>Second sheet</sheetTitle>
                  </TCEforms>
              <type>array</type>
              <el>
                <show_forgot_password>
                          <TCEforms>
                                  <label>Yes, I do:</label>
                                  <config>
                                          <type>check</type>
                                  </config>
                          </TCEforms>
                </show_forgot_password>
              </el>
            </ROOT>
      </s_welcome>
    </sheets>
  </T3DataStructure>
   
          '
      )
  );

The result from configuration is a form which looks like this:

 


Clicking "Second sheet" will now show the other Data Structure:

 


If you look at the XML stored in the database field this is how it looks:

 

  <?xml version="1.0" encoding="iso-8859-1" standalone="yes" ?>
  <T3FlexForms>
          <meta>
                  <currentSheetId>s_welcome</currentSheetId>
          </meta>
          <data>
                  <sDEF>
                          <lDEF>
                                  <header>
                                          <vDEF>This is a header</vDEF>
                                  </header>
                                  <message>
                                          <vDEF>Here goes the message

  This is another line in the message!</vDEF>
                                  </message>
                          </lDEF>
                  </sDEF>
                  <s_welcome>
                          <lDEF>
                                  <show_forgot_password>
                                          <vDEF>1</vDEF>
                                  </show_forgot_password>
                          </lDEF>
                  </s_welcome>
          </data>
  </T3FlexForms>

Notice how the data of the two sheets are separated.

Example: Rich Text Editor in FlexForms

Creating a RTE in FlexForms is done by adding "defaultExtras" content to the <TCEforms> tag:

  <TCEforms>
      <config>
          <type>text</type>
          <cols>48</cols>
          <rows>5</rows>
      </config>
      <label>Subtitle</label>
      <defaultExtras>richtext[*]:rte_transform[mode=ts_css]</defaultExtras>
  </TCEforms>

Handling languages in FlexForms

FlexForms allows you to handle translations of content in two ways. But before you can enable those features you have to install the extension "static_info_tables" which contains country names and ISO-language codes which are the ones by which FlexForms stores localized content:

 


Secondly, you have to configure languages in the Database:

 


And finally, you have to make sure that each of these languages points to the right ISO code:

 


 

Localization method #1:

Immediately you will see that the form has got a language selector and if you select both languages and save the form you will see an additional set of fields for Danish:

 


 

Notice: If the "<meta><langDisable>" value is true then you will not see any languages of course.

 

The data XML in the data base will look like this:

  <?xml version="1.0" encoding="iso-8859-1" standalone="yes" ?>
  <T3FlexForms>
          <meta>
                  <currentSheetId>sDEF</currentSheetId>
                  <currentLangId>
                          <numIndex index="0">DEF</numIndex>
                          <numIndex index="1">DA</numIndex>
                  </currentLangId>
          </meta>
          <data>
                  <sDEF>
                          <lDEF>
                                  <header>
                                          <vDEF>This is a header</vDEF>
                                  </header>
                                  <message>
                                          <vDEF>Here goes the message

  This is another line in the message!</vDEF>
                                  </message>
                          </lDEF>
                          <lDA>
                                  <header>
                                          <vDEF>Dette er en overskrift</vDEF>
                                  </header>
                                  <message>
                                          <vDEF>Her skal beskeden indsættes

  Dette er en anden linie i beskeden.</vDEF>
                                  </message>
                          </lDA>
                  </sDEF>
                  <s_welcome>
                          <lDEF>
                                  <show_forgot_password>
                                          <vDEF>1</vDEF>
                                  </show_forgot_password>
                          </lDEF>
                  </s_welcome>
          </data>
  </T3FlexForms>

Notice the tag <lDA> which contains the Danish translation!

 

Localization method #2:

In the first method of localization each language can potentially contain a differently structured data set. This is possible because as soon as a DS defines sections with array objects inside the number of objects can be individual!

The second method of localization handles each language on the value level instead, thus requiring a translation for each and every field in the default language! You enable this by setting "<meta><langChildren>" to "1".

The editing form will now look like this:

 


You can see that the Danish translation for the header is grouped with the default header and likewise for the "Message" field.

The difference is also seen in the <T3FlexForms> content:

 

  <?xml version="1.0" encoding="iso-8859-1" standalone="yes" ?>
  <T3FlexForms>
          <meta>
                  <currentSheetId>sDEF</currentSheetId>
                  <currentLangId>
                          <numIndex index="0">DEF</numIndex>
                          <numIndex index="1">DA</numIndex>
                  </currentLangId>
          </meta>
          <data>
                  <sDEF>
                          <lDEF>
                                  <header>
                                          <vDEF>This is a header</vDEF>
                                          <vDA>Dette er en overskrift</vDA>
                                  </header>
                                  <message>
                                          <vDEF>Here goes the message

  This is another line in the message!</vDEF>
                                          <vDA>Here goes the message

  This is another line in the message!</vDA>
                                  </message>
                          </lDEF>
                  </sDEF>
                  <s_welcome>
                          <lDEF>
                                  <show_forgot_password>
                                          <vDEF>1</vDEF>
                                  </show_forgot_password>
                          </lDEF>
                  </s_welcome>
          </data>
  </T3FlexForms>

You can see the Danish counterparts to the default values are stored in tags named "<vDA>" on the same level as "<vDEF>" is located.

NOTICE: The two localization methods are NOT compatible! You cannot suddenly change from the one method to the other without having to do some conversion of the data format. That is obvious when you look at how the two methods also require different data structures underneath!

To top


Valid XHTML 1.0!