.. ================================================== .. FOR YOUR INFORMATION .. -------------------------------------------------- .. -*- coding: utf-8 -*- with BOM. .. include:: ../../../Includes.txt .. _columns-flex: TYPE: "flex" ^^^^^^^^^^^^ Rendering 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. .. only:: html .. contents:: :local: :depth: 1 .. _columns-flex-properties: Properties """""""""" .. container:: ts-properties =========================================== ========= Property Data Type =========================================== ========= `ds`_ array `ds\_tableField`_ string `ds\_pointerField`_ string `ds\_pointerField\_searchParent`_ string `ds\_pointerField\_searchParent\_subField`_ string `type`_ string =========================================== ========= Property details """""""""""""""" .. only:: html .. contents:: :local: :depth: 1 .. _columns-flex-properties-type: type ~~~~ .. container:: table-row Key type Datatype string Description *[Must be set to "flex"]* .. _columns-flex-properties-ds-pointerfield: ds\_pointerField ~~~~~~~~~~~~~~~~ .. container:: table-row Key ds\_pointerField Datatype string Description Field name(s) in the record which point to the field where the key for "ds" is found. Up to two field names can be specified comma separated. .. _columns-flex-properties-ds: ds ~~ .. container:: table-row Key ds Datatype array Description Data Structure(s) defined in an array. Each key is a value that can be pointed to by :ref:`ds_pointerField `. Default key is "default" which is what you should use if you do not have a :code:`ds_pointerField` value of course. If you specified more than one :code:`ds_pointerField`, the keys in this "ds" array should contain comma-separated value pairs where the asterisk \* matches all values (see the example below). If you don't need to switch for the second ds\_pointerField, it's also possible to use only the first :code:`ds_pointerField`'s value as a key in the "ds" array without necessarily suffixing it with ",\*" for a catch-all on the second :code:`ds_pointerField`. For each value in the array there are two options: - Either enter XML directly - Make a reference to an external XML file **Example with XML directly entered:** .. code-block:: php 'config' => array( 'type' => 'flex', 'ds_pointerField' => 'list_type', 'ds' => array( 'default' => ' array input 48 ', ) ) **Example with XML in external file:** (File reference is relative) .. code-block:: php 'config' => array( 'type' => 'flex', 'ds_pointerField' => 'list_type', 'ds' => array( 'default' => 'FILE:EXT:mininews/flexform_ds.xml', ) ) **Example using two ds\_pointerFields:** .. code-block:: php 'config' => array( 'type' => 'flex', 'ds_pointerField' => 'list_type,CType', 'ds' => array( 'default' => 'FILE:...', 'tt_address_pi1,list' => 'FILE:EXT:tt_address/pi1/flexform.xml', // DS for list_type=tt_address_pi1 and CType=list '*,table' => 'FILE:EXT:css_styled_content/flexform_ds.xml', // DS for CType=table, no matter which list_type value 'tx_myext_pi1' => 'FILE:EXT:myext/flexform.xml', // DS for list_type=tx_myext_pi1 without specifying a CType at all ) ) .. _columns-flex-properties-ds-tablefield: ds\_tableField ~~~~~~~~~~~~~~ .. container:: table-row Key ds\_tableField Datatype string Description Contains the value "[table]:[field name]" from which to fetch Data Structure XML. :ref:`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: .. code-block:: php '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', ) ), .. _columns-flex-properties-ds-pointerfield-searchparent: ds\_pointerField\_searchParent ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. container:: table-row Key ds\_pointerField\_searchParent Datatype string Description 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. .. _columns-flex-properties-ds-pointerfield-searchparent-subfield: ds\_pointerField\_searchParent\_subField ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. container:: table-row Key ds\_pointerField\_searchParent\_subField Datatype string Description 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. .. _columns-flex-ds-pointer: 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 "". For general information about the backbone of a Data Structure, please refer to the ` chapter in the Core API manual `. .. _columns-flex-facts: 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 :code:`\TYPO3\CMS\Core\Utility\GeneralUtility::xml2array()`)! The "TCA" information needed to generate the FlexForm fields are found inside a 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: - "unique" and "uniqueInPid" evaluation is not available - You cannot nest FlexForm configurations inside of FlexForms. - Charset follows that of the current backend (since TYPO3 CMS 4.7, the only accepted character encoding is UTF-8. When storing FlexForm information in external files, make sure that they are using UTF-8 too). .. _columns-flex-tceforms: extensions for "" """"""""""""""""""""""""""""""""""""""""""""" For FlexForms the DS is extended with a tag, "" 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 "reload"inside . 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 tag for mode fields with 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 documents the extension elements: .. _columns-flex-tceforms-array: Array Elements ~~~~~~~~~~~~~~ .. _columns-flex-tceforms-array-meta: '''''' .. container:: table-row Element Description Can contain application specific meta settings. For FlexForms this means a definition of how languages are handled in the form. Child elements .. _columns-flex-tceforms-array-application-tag: <[application tag]> ''''''''''''''''''' .. container:: table-row Element <[application tag]> Description In this case the application tag is "" Child elements *A direct reflection of a ['columns']['field name']['config'] PHP array configuring a field in TCA. As XML this is expressed by array2xml()'s output. See example below.* .. _columns-flex-tceforms-array-root-tceforms: '''''''''''''''' .. container:: table-row Element Description For elements in the DS you can add application specific information about the sheet that the element represents. Child elements .. _columns-flex-tceforms-value: Value Elements ~~~~~~~~~~~~~~ .. columns-flex-tceforms-value-langdisable: ''''''''''''' .. container:: table-row Element Format boolean, 0/1 Description 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. .. _columns-flex-tceforms-value-langchildren: '''''''''''''' .. container:: table-row Element Format boolean, 0/1 Description If set, then localizations are bound to the default values 1-1 ("value" level). Otherwise localizations are handled on "structure level" .. _columns-flex-tceforms-value-sheettitle: '''''''''''' .. container:: table-row Element Format string or LLL reference Description Specifies the title of the sheet. .. _columns-flex-tceforms-value-sheetdescription: '''''''''''''''''' .. container:: table-row Element Format string or LLL reference Description Specifies a description for the sheet shown in the flexform. .. _columns-flex-tceforms-value-sheetshortdescr: ''''''''''''''''' .. container:: table-row Element Format string or LLL reference Description Specifies a short description of the sheet used in the tab-menu. .. _columns-flex-sheets: 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). .. _columns-flex-data-format: FlexForm data format, """"""""""""""""""""""""""""""""""" When saving FlexForm elements the content is stored as XML using :code:`\TYPO3\CMS\Core\Utility\GeneralUtility::array2xml_cs()` to convert the internal PHP array to XML format. The structure is as follows: .. _columns-flex-data-format-array: Array Elements ~~~~~~~~~~~~~~ .. _columns-flex-data-format-array-t3flexforms: ''''''''''''' .. container:: table-row Element Description Document tag Child elements .. _columns-flex-data-format-array-meta: '''''' .. container:: table-row Element Description Meta data for the content. For instance information about which sheet is active etc. Child elements .. _columns-flex-data-format-array-data: '''''' .. container:: table-row Element Description Contains the data; sheets, language sections, field and values Child elements .. _columns-flex-data-format-array-sheet: ''''''' .. container:: table-row Element Description Contains the data for each sheet in the form. If there are no sheets, the default sheet "" is always used. Child elements .. _columns-flex-data-format-array-sdef: '''''' .. container:: table-row Element <[sheet keys]> Description For each sheet it contains elements for each language. If is false then all languages are stored on this level, otherwise only the tag is used. Child elements .. _columns-flex-data-format-array-ldef: '''''' .. container:: table-row Element <[language keys]> Description For each language the fields in the form will be available on this level. Child elements <[field name]> .. _columns-flex-data-format-array-field-name: <[field name]> '''''''''''''' .. container:: table-row Element <[field name]> Description For each field name there is at least one element with the value, . If is true then there will be a tag for each language holding localized values. Child elements .. _columns-flex-data-format-array-currentlangid: ''''''''''''''' .. container:: table-row Element Description Numerical array of language ISO codes + "DEF" for default which are currently displayed for editing. Child elements .. _columns-flex-data-format-value: Value Elements ~~~~~~~~~~~~~~ .. _columns-flex-data-format-value-vdef: '''''' .. container:: table-row Element Format string Description Content of the field in default or localized versions .. _columns-flex-example-simple: Example: Simple FlexForm ~~~~~~~~~~~~~~~~~~~~~~~~ The extension "examples" provides some sample FlexForms. The "simple FlexForm" plugin provides a very basic configuration with just a select-type field to choose a page from the "pages" table. .. figure:: ../../../Images/TypeFlexSimple.png :alt: A simple FlexForm field A plugin with a simple, one-field flexform The DS used to render this field is found in the file "flexform\_ds1.xml" inside the "examples" extension. Notice the tags: .. code-block:: xml 1 LLL:EXT:examples/locallang_db.xml: examples.pi_flexform.sheetGeneral array select LLL:EXT:examples/locallang_db.xml:examples.pi_flexform.choosePage 0 pages ORDER BY title 0 1 It's clear that the contents of is a direct reflection of the field configurations we normally set up in the $TCA array. The Data Structure for this FlexForm is loaded in the "pi\_flexform" field of the "tt\_content" table by adding the following to the ext\_tables.php file of the "examples" extension: .. code-block:: php $TCA['tt_content']['types']['list']['subtypes_addlist'][$_EXTKEY . '_pi1'] = 'pi_flexform'; \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPiFlexFormValue($_EXTKEY . '_pi1', 'FILE:EXT:examples/flexform_ds1.xml'); In the first line the tt\_content field "pi\_flexform" is added to the display of fields when the Plugin type is selected and set to "examples\_pi1". In the second line 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" using the Admin > Configuration module, we can see the following: .. figure:: ../../../Images/TypeFlexConfigurationCheck.png :alt: Checking the configuration Checking the TCA configuration for the newly added Flexform As you can see there are quite a few extensions that have added pointers to their Data Structures. Towards the bottom we can find the one we have just been looking at. .. _columns-flex-example-sheets: Example: FlexForm with two sheets ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In this example we create a FlexForm field with two "sheets". Each sheet can contain a separate FlexForm structure. We build it up on top of the previous example, so the first sheet still has a select-type field related to the "pages" table. In the second sheet, we add a simple input field and a text field. .. code-block:: xml 1 LLL:EXT:examples/locallang_db.xml: examples.pi_flexform.sheetGeneral array select LLL:EXT:examples/locallang_db.xml:examples.pi_flexform.choosePage 0 pages ORDER BY title 0 1 LLL:EXT: examples/locallang_db.xml:examples.pi_flexform.s_Message array
input 30
text 40 5
The part that is different from the first Data Structure is highlighted in bold. The result from this configuration is a form which looks like this: .. figure:: ../../../Images/TypeFlexSheet1.png :alt: The first sheet The first sheet of our more complex FlexForm This looks very much like the first example, but notice the second tab. Clicking on "Message", we can access the second sheet which shows some other fields: .. figure:: ../../../Images/TypeFlexSheet2.png :alt: The second sheet The second sheet of our more complex FlexForm If you look at the XML stored in the database field "pi\_flexform" this is how it looks: .. code-block:: xml 9 My Header And my message. On several lines. Notice how the data of the two sheets are separated (sheet names highlighted in bold above). .. _columns-flex-example-rte: Example: Rich Text Editor in FlexForms ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Creating a RTE in FlexForms is done by adding "defaultExtras" content to the tag: .. code-block:: xml text 48 5 richtext[*]:rte_transform[mode=ts_css] .. _columns-flex-languages: 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: .. figure:: ../../../Images/TypeFlexStaticInfoTablesInstalled.png :alt: Extension static\_info\_tables is installed Checking that extension static\_info\_tables is installed Then you must configure languages in the database: .. figure:: ../../../Images/TypeFlexSystemLanguages.png :alt: System languages Checking that system languages are defined And finally, you have to make sure that each of these languages points to the right ISO code: .. figure:: ../../../Images/TypeFlexLanguageCheckIsoCode.png :alt: Check ISO code Checking that system languages have the proper ISO codes By default, you will not see any changes. Indeed if you look at the example XML displayed above, you will notice the following line, at the top, in the "meta" section: .. code-block:: xml 1 This means that translation of the FlexForm is disabled. In the example above, the FlexForm is part of a content element. That content element can still be translated as usual. What we're going to look at below is how a FlexForm field may end up containing its own translations. There are two methods for this. .. _columns-flex-languages-method1: Localization method #1 ~~~~~~~~~~~~~~~~~~~~~~ The first localization method just requires to change the "langDisable" flag mentioned above to 0: .. code-block:: xml 0 This means that translations are now allowed for that FlexForm. This is how it looks like: .. figure:: ../../../Images/TypeFlexLocalizationMethod1.png :alt: Translations with method 1 All FlexForm fields are grouped by language The data XML in the data base looks like this: .. code-block:: xml 9 My Header And my message. On several lines. Hallo! Das is auf Deutsch! Note how each language is stored separately at a level above the "field" level. Each language tag carries an attribute identifying the language like "lDE" or "lEN". .. _columns-flex-languages-method2: 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 the "langChildren" tag to "1" in the "meta" section: .. code-block:: xml 0 1 The editing form will now look like this: .. figure:: ../../../Images/TypeFlexLocalizationMethod2.png :alt: Translations with method 2 Fields are grouped together You can see how all translation fields for the "Header" are grouped together with the default header. Likewise for the "Message" field. The difference is also seen in the content: .. code-block:: xml My header Hallo! My header My header And my message. On several lines. Das is auf Deutsch! And my message. On several lines. And my message. On several lines. In this case, there's only on "language" tag per sheet and all values are repeated with a language index attribute to tell them apart. The additional "value" tags with an index attribute like "vDE.vDEFbase" are used to store the previous value that the field contained, so that a translation diff view can be displayed: .. figure:: ../../../Images/TypeFlexDiffView.png :alt: Translations differences Viewing changes in original and translations .. warning:: 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!