Newer
Older
Server configurations.
To decide which Parameter should be placed on *Form.parameter* and which on *FormElement.parameter*: If LDAP access is ...
* only necessary in one *FormElement*, most useful setup is to specify all values in that specific *FormElement*,
* needed on multiple *FormElement*s (of the same *Form*, e.g. one *input* with *typeAhead*, one *note* and one *action*), it's more
efficient to specify the base parameter *ldapServer*, *ldapBaseDn* in *Form.parameter* and the rest on the current
*FormElement*.
+-----------------------------+----------------------------------+---------------------------------------------------------------+------+-------------+----------+
| Parameter | Example | Description | Form | FormElement | Used for |
+=============================+==================================+===============================================================+======+=============+==========+
| ldapServer | directory.example.com | Hostname. For LDAPS: `ldaps://directory.example.com:636` | x | x | TA, FSL |
+-----------------------------+----------------------------------+---------------------------------------------------------------+------+-------------+----------+
| ldapBaseDn | ou=Addressbook,dc=example,dc=com | Base DN to start the search | x | x | TA, FSL |
+-----------------------------+----------------------------------+---------------------------------------------------------------+------+-------------+----------+
| ldapAttributes | cn, email | List of attributes to save in STORE_LDAP | x | x | FSL |
+-----------------------------+----------------------------------+---------------------------------------------------------------+------+-------------+----------+
| ldapSearch | (mail=john.doe@example.com) | Regular LDAP search expression | x | x | FSL |
+-----------------------------+----------------------------------+---------------------------------------------------------------+------+-------------+----------+
| ldapTimeLimit | 3 (default) | Maximum time to wait for an answer of the LDAP Server | x | x | TA, FSL |
+-----------------------------+----------------------------------+---------------------------------------------------------------+------+-------------+----------+
| ldapUseBindCredentials | ldapUseBindCredentials=1 | Use LDAP_1_* credentials from config-qfq-php_ for ldap_bind() | x | x | TA, FSL |
+-----------------------------+----------------------------------+---------------------------------------------------------------+------+-------------+----------+
| typeAheadLdap | | Enable LDAP as 'Typeahead' data source | | x | TA |
+-----------------------------+----------------------------------+---------------------------------------------------------------+------+-------------+----------+
| typeAheadLdapSearch | `(|(cn=*?*)(mail=*?*))` | Regular LDAP search expression, returns upto typeAheadLimit | x | x | TA |
+-----------------------------+----------------------------------+---------------------------------------------------------------+------+-------------+----------+
| typeAheadLdapSearchPrefetch | `(mail=?)` | Regular LDAP search expression, typically return one record | x | x | TA |
+-----------------------------+----------------------------------+---------------------------------------------------------------+------+-------------+----------+
| typeAheadLdapSearchPerToken | | Split search value in token and OR-combine every search with | x | x | TA |

Carsten Rose
committed
| | | the individual tokens | | | |

Carsten Rose
committed
+-----------------------------+----------------------------------+---------------------------------------------------------------+------+-------------+----------+
| typeAheadLdapValuePrintf | `'%s / %s', cn, mail` | Custom format to display attributes, as `value` | x | x | TA |
+-----------------------------+----------------------------------+---------------------------------------------------------------+------+-------------+----------+
| typeAheadLdapIdPrintf | `'%s', mail` | Custom format to display attributes, as `id` | x | x | TA |
+-----------------------------+----------------------------------+---------------------------------------------------------------+------+-------------+----------+
| typeAheadLimit | 20 (default) | Result will be limited to this number of entries | x | x | TA |
+-----------------------------+----------------------------------+---------------------------------------------------------------+------+-------------+----------+
| typeAheadPedantic | typeAheadPedantic=0 | Turn off 'pedantic' mode - allow any values (see below) | x | x | TA |
+-----------------------------+----------------------------------+---------------------------------------------------------------+------+-------------+----------+
| typeAheadMinLength | 2 (default) | Minimum number of characters before starting the search | x | x | TA |
+-----------------------------+----------------------------------+---------------------------------------------------------------+------+-------------+----------+
| fillStoreLdap | | Activate `Fill STORE LDAP` with the first retrieved record | | x | FSL |
+-----------------------------+----------------------------------+---------------------------------------------------------------+------+-------------+----------+
* *typeAheadLimit*: there might be a hard limit on the server side (e.g. 100) - which can't be extended.
* *ldapUseBindCredentials* is only necessary if `anonymous` access is not possible. RDN and password has to be configured in

Carsten Rose
committed
config-qfq-php_.
.. _LDAP_Typeahead:
Typeahead (TA)
--------------
*Typeahead* offers continous searching of a LDAP directoy by using a regular *FormElement* of type *text*.
The *FormElement.parameter*=*typeAheadLdap* will trigger LDAP searches on every user **keystroke**
(starting after *typeAheadMinLength* keystrokes) for the current *FormElement* - this is different from *dynamicUpdate*
(triggered by leaving focus of an input element). Typeahead delivers a list of elements.
* *FormElement.parameter.typeAheadLdap* - activate the mode *Typeahead* - no value is needed, the existence is suffucient.
* *Form.parameter* or *FormElement.parameter*:
* *ldapServer* = `directory.example.com`
* *ldapBaseDn* = `ou=Addressbook,dc=example,dc=com`
* *typeAheadLdapSearch* = `(|(cn=*?*)(mail=*?*))`
* *typeAheadLdapValuePrintf* = `'%s / %s', cn, email`

Carsten Rose
committed
* *typeAheadLdapIdPrintf* = `'%s', email`
All fetched LDAP values will be formatted with:
* *typeAheadLdapValuePrintf*, shown to the user in a drop-down box and

Carsten Rose
committed
* *typeAheadLdapIdPrintf*, which represents the final data to save.

Carsten Rose
committed
The `id/value` translation is compareable to a regular select drop-down box with id/value pairs.
Only attributes, defined in *typeAheadLdapValuePrintf* / *typeAheadLdapIdPrintf* will be fetched from the LDAP directory.
To examine all possible values of an LDAP server, use the commandline tool `ldapsearch`. E.g.::
ldapsearch -x -h directory.example.com -L -b ou=Addressbook,dc=example,dc=com "(mail=john.doe@example.com)"
All occurrences of a '?' in *ldapSearch* will be replaced by the user data typed in via the text-*FormElement*.
The typed data will be escaped to fulfill LDAP search limitations.
Regular *Form* variables might be used on all parameter and will be evaluated during form load (!) - *not* at the time when
Pedantic
^^^^^^^^
The *typeAheadPedantic* mode ensures that the typed value (technically this is the value of the *id*, latest in the moment
when loosing the focus) is valid (= exists on the LDAP server or is defined in `typeAheadSql`).
If the user typed something and that is not a valid *id*, the client (=browser) will delete the input when losing the focus.
To identify the exact *id*, an additional search filter is necessary: `typeAheadLdapSearchPrefetch` - see next topic.
*typeAheadPedantic* is active by default when *typeAheadLdap* or *typeAheadSql* is defined, but can be turned off with
*typeAheadPedantic=0*.
* *Form.parameter* or *FormElement.parameter*:
* *typeAheadPedantic=0*
Prefetch
^^^^^^^^
After 'form load' with an existing record, the user expects to see the previous saved data. In case there is an *id* to
*value* translation, the *value* does not exist in the database, instead it has to be fetched again dynamically.
A precise LDAP or SQL query has to be defined to force this:
* *Form.parameter* or *FormElement.parameter*:
* *typeAheadLdapSearchPrefetch* = `(mail=?)`
* *typeAheadSqlPrefetch* = `SELECT firstName, ' ', lastName FROM person WHERE id = ?`
This situation also applies in *pedantic* mode to verify the user input after each change.

Carsten Rose
committed
PerToken
^^^^^^^^

Carsten Rose
committed
Sometimes a LDAP server only provides attributes like 'sn' and 'givenName', but not 'displayName' or another practial
combination of multiple attributes - than it is difficult to search for 'firstname' *and* (=human AND) 'lastname'.
E.g. 'John Doe', results to search like `(|(sn=*John Doe*)(givenName=*John Doe*))` which will be probably always be empty.
Instead, the user input has to be split in token and the search string has to repeated for every token.

Carsten Rose
committed
* *Form.parameter* or *FormElement.parameter*:
* *typeAheadLdapSearchPerToken* - no value needed.

Carsten Rose
committed
This will repeat the search string per token.

Carsten Rose
committed
E.g.::
User search string: X Y

Carsten Rose
committed
Ldap search string: (|(a=*?*)(b=*?*))
Result: (& (|(a=*X*)(b=*X*)) (|(a=*Y*)(b=*Y*))

Carsten Rose
committed
Attention: this option is only useful in specific environments. Only use it, if it is really needed. The query becomes

Carsten Rose
committed
much more cpu / IO intensive.

Carsten Rose
committed
.. _Fill_LDAP_STORE:
Fill STORE LDAP (FSL)
---------------------

Carsten Rose
committed
Before processing a *FormElement*, an optional configured FSL-action loads **one** record from a LDAP directory and stores
the named attributes in STORE_LDAP. If the LDAP search query selects more than one record, only the first record is processed.
The attributes names always becomes lowercase (PHP implentation detail on get_ldap_entries()) in the store. To make
accessing STORE_LDAP easily, the keys are implemented case insensitive for this specific store. FLS is triggered during *Form*-...
* load,
* dynamic update,
* save.
The FLS happens *before* the *FormElement* processing starts. Therefore the fetched LDAP data (specified by *ldapAttributes*),
are available via `{{<attributename>:L:allbut:s}}` during the regular *FormElement* processing. Take care to specify

Carsten Rose
committed
a sanitize class and optional escaping on further processing of those data.
Also, the STORE LDAP remains filled, during the whole form processing time. E.g. if the values are needed for a person
name and email, it's sufficient to fire one FSL on the first FormElement Action element, and use the same values during further FormElement
Action Elements.
.. important::
LDAP access might slow down the *Form* processing on load, update or save! The timeout (default: 3 seconds) have
to be multiplied by the number of accesses. E.g. a broken LDAP connection and 3 *FormElements* with *FSL*
results to 9 seconds delay on save. Also be prepared not to receive the expected data.
* *FormElement.parameter.fillStoreLdap* - activate the mode *Fill S* - no value is needed, the existence is sufficient.
* *Form.parameter* or *FormElement.parameter*:
* *ldapServer* = `directory.example.com`
* *ldapBaseDn* = `ou=Addressbook,dc=example,dc=com`
* *typeAheadLdapSearch* = `(|(cn=*?*)(mail=*?*))`
* *ldapAttributes* = `givenName, sn, telephoneNumber, email`
* *ldapSearch* = `(mail={{email:F0:alnumx:l}})`
After filling the store, access the content via `{{<attributename>:L:allbut:s}}`.

Carsten Rose
committed
Form
====

Carsten Rose
committed
General
-------
* Forms will be created by using the *Form Editor* on the Typo3 frontend (HTML form).
* The *Form editor* itself consist of two predefined QFQ forms: *form* and *formElement* - these forms are often updated
during the installation of new QFQ versions.

Carsten Rose
committed
* Every form consist of a) a *Form* record and b) multiple *FormElement* records.
* A form is assigned to a *table*. Such a table is called the *primary table* for this form.

Carsten Rose
committed
* *Simple* form: the form acts on one record, stored in one table.
* The form will create necessary SQL commands for insert, update and delete (only primary record) automatically.
* *Advanced* form: the form acts on multiple records, stored in more than one table.
* Fields of the primary table acts like a *simple* form, all other fields have to be specified with *action/afterSave* records.

Carsten Rose
committed
* *Multi* form: (multi-form_) the form acts simultaneously on more than one record. All records use the same *FormElements*.

Carsten Rose
committed
* The *FormElements* are defined as a regular *simple* / or *advanced* form, plus an SQL Query, which selects and

Carsten Rose
committed
iterates over all records. Those records will be loaded at the same time.
* *Delete* form: any form can be used as a form to `delete-record`_.
* Form mode: The parameter 'r' (given via URL or via SIP) decide if the form is in mode:
* `New`:
* Missing parameter 'r' or 'r=0'
* On form load, no record is displayed.
* Saving the form creates a new primary record.
* E.g.: `http://example.com/index.php?id=home&form=Person` or `http://example.com/index.php?id=home&form=Person&r=0`
* `Edit`:
* Parameter 'r>0'
* On form load, the specified record (<tablename>.id= <r>) will be loaded and displayed.
* Saving the form will update the existing record.
* E.g.: `http://example.com/index.php?id=home&form=Person&r=123`
* Providing additional parameter:
Often, it is necessary to store additional, for the user not visible, parameter in a record. See `form-magic`_.
* Display a form:
* Create a QFQ tt_content record on a Typo 3 page.
* Inside the QFQ record: `form = <formname>`. E.g.:
* Static: `form = Person`

Carsten Rose
committed
* Dynamic: `form = {{form:SE}}` (the left `form` is a keyword for QFQ, the right `form` is a free chooseable variable name)
* With the `Dynamic` option, it's easily possible to use one Typo3 page and display different forms on that specific
page. This is nice to configure few Typo 3 pages. The disadvantage is that the user might loose the navigation.

Carsten Rose
committed

Carsten Rose
committed
.. _record_locking:
Record locking
--------------

Carsten Rose
committed
Forms and 'record delete'-function support basic record locking. A user opens a form: starting with the first change of content, a
record lock will be acquired in the background. If the lock is denied (e.g. another user already owns a lock on the record) an

Carsten Rose
committed
By default the record lock mode is 'exclusive' and the default timeout is 15 minutes. Both can be configured per form.
The general timeout can also be configured in configuration_ (will be copied to the form during creating the form).

Carsten Rose
committed
The lock timeout counts from the first change, not from the last modification on the form.

Carsten Rose
committed
If a timeout expires, the lock becomes invalid. During the next change in a form, the lock is acquired again.

Carsten Rose
committed
A lock is assigned to a record of a table. Multiple forms, with the same primary table, uses the same lock for a given record.
If a `Form` acts on further records (e.g. via FE action), those records are not protected by this basic record locking.
If a user tries to delete a record and another user already owns a lock on that record, the delete action is denied.
If there are different locking modes in multiple forms, the most restricting mode applies for the current lock.
Exclusive
^^^^^^^^^
An existing lock on a record forbids any write action on that record.
Advisory
^^^^^^^^
An existing lock on a record informs the user that another user is currently working on that record. Nevertheless,
writing is allowed.
None
^^^^
No locking at all.

Carsten Rose
committed
.. _comment-space-character:
Comment- and space-character
----------------------------
The following applies to the fields `Form.parameter` and `FormElement.parameter`:

Carsten Rose
committed
* Lines will be trimmed - leading and trailing spaces will be removed.
* If a leading and/or trailing space is needed, escape it: \\ hello world \\ > ' hello world '.
* Lines starting with a '#' are treated as a comment and will not be parsed. Such lines are treated as 'empty lines'.

Carsten Rose
committed

Carsten Rose
committed
.. _form-main:
Definition
----------

Carsten Rose
committed
+-------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+
| Name | Description |
+=========================+====================================================================================================================================================+
|Name | Unique and speaking name of the *Form*. Form will be identified by this name. Use only '[a-zA-Z0-9._+-]'. _`form-name` |
+-------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+
|Title | Title, shown on/above the form. _`form-title` |
+-------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+
|Note | Personal editor notes. _`form-note` |
+-------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+
|Table | Primary table of the form. _`form-tablename` |
+-------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+
|Primary Key | Primary key of the indicated table. Only needed if != 'id'. _`form-primary-key` |
+-------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+
|Required Parameter NEW | Name of required SIP parameter to create a new record (r=0), separated by comma. '#' as comment delimiter. See `form-requiredParameter`_ |
+-------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+
|Required Parameter EDIT | Name of required SIP parameter to edit an existing record (r>0), separated by comma. '#' as comment delimiter. See `form-requiredParameter`_ |

Carsten Rose
committed
+-------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+
|Permit New | 'sip, logged_in, logged_out, always, never' (Default: sip): See `form-permitNewEdit`_ |
+-------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+
|Permit Edit | 'sip, logged_in, logged_out, always, never' (Default: sip): See `form-permitNewEdit`_ |
+-------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+
|Escape Type Default | See `variable-escape`_. |
+-------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+
|Show button | 'new, delete, close, save' (Default: 'new,delete,close,save'): Shown named buttons in the upper right corner of the form. See `form-showButton`_ |
+-------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+

Carsten Rose
committed
|Forward Mode | 'auto | close | no | url | url-skip-history | url-sip | url-sip-skip-history' (Default: auto): See `form-forward`_. |

Carsten Rose
committed
+-------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+
|Forward (Mode) Page | a) URL / Typo3 page id/alias or b) Forward Mode (via '{{...}}') or combination of a) & b). See `form-forward`_. |

Carsten Rose
committed
+-------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+
|labelAlign | Label align (default/left/center/right)/ Default: 'default' (defined by Config). |
+-------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+

Carsten Rose
committed
|Parameter | Misc additional parameters. See `form-parameter`_. |
+-------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+
|BS Label Columns | The bootstrap grid system is based on 12 columns. The sum of *bsLabelColumns*, |
+-------------------------+ *bsInputColumns* and *bsNoteColumns* should be 12. These values here are the base values |
|BS Input Columns | for all *FormElements*. Exceptions per *FormElement* can be specified per *FormElement*. |

Carsten Rose
committed
+-------------------------+ Default: label=col-md-3, input=col-md-6, note=col-md-3. See `form-layout`_. |

Carsten Rose
committed
|BS Note Columns | |
+-------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+
|multiMode | NOT IMPLEMENTED - 'none, horizontal, vertical' (Default 'none') |
+-------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+
|multiSql | NOT IMPLEMENTED - Optional. SQL Query which selects all records to edit. |
+-------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+
|multiDetailForm | NOT IMPLEMENTED - Optional. Form to open, if a record is selected to edit (double click on record line) |
+-------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+
|multiDetailFormParameter | NOT IMPLEMENTED - Optional. Translated Parameter submitted to detailform (like subrecord parameter) |
+-------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+
.. _`form-permitNewEdit`:

Carsten Rose
committed
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
permitNew & permitEdit
^^^^^^^^^^^^^^^^^^^^^^
Depending on `r`, the following access permission will be taken:
* `r=0` - permitNew
* `r>0` - permitEdit
+------------+---------------------------------------------------------------------------------------------------+
| Option | Description |
+============+===================================================================================================+
| sip | The parameter 'form' and 'r' must be supplied via SIP or hard coded in the QFQ tt_content record. |
+------------+---------------------------------------------------------------------------------------------------+
| logged_in | The form will only be shown if the current User is logged in as a FE User |
+------------+---------------------------------------------------------------------------------------------------+
| logged_out | The form will only be shown if the current User is *not* logged in as a FE User |
+------------+---------------------------------------------------------------------------------------------------+
| always | No access restriction, the form will always be shown |
+------------+---------------------------------------------------------------------------------------------------+
| never | The form will never be shown |
+------------+---------------------------------------------------------------------------------------------------+
* `sip`
* is *always* the preferred way. With 'sip' it's not necessary to differ between logged in or not, cause the SIP
only exist and is only valid, if it's created via QFQ/report earlier. This means 'creating' the SIP implies
'access granted'. The grant will be revoked when the QFQ session is destroyed - this happens when a user loggs out or
the web browser is closed.
* `logged_in` / `logged_out`: for forms which might be displayed without a SIP, but maybe on a protected or even
unprotected page. *The option is probably not often used.*
* `always`: such a form is always allowed to be loaded.
* `permitNew=always`: Public accessible forms (e.g. for registration) will allow users to fill and save
the form.
* `permitEdit=always`: Public accessible forms will allow users to update existing data. This
is dangerous, cause the URL parameter (recordId) 'r' might be changed by the user (URL manipulating) and therefore
the user might see and/or change data from other users. *The option is probably not often used.*
* `never`: such a form is not allowed to be loaded.
* `permitNew=never`: Public accessible forms. It's not possible to create new records.
* `permitEdit=none`: Public accessible forms. It's not possible to update records.

Carsten Rose
committed
.. _`form-requiredParameter`:
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Comma separated list of variable names. On form load, an error message will be shown in case of missing parameters.
The parameters must be given by SIP.
The list of required parameter has to be defined for `New` (r=0, create a new record) and for `Edit` (r>0, edit existing
record).

Carsten Rose
committed
Optional a comment might be attached after the parameter definition.
E.g.: ::
New: grId, pId # Always specify a person, grId2
Edit: pId

Carsten Rose
committed
.. _`form-showButton`:

Carsten Rose
committed
showButton
^^^^^^^^^^
Display or hide the button `new`, `delete`, `close`, `save`.

Carsten Rose
committed
* *new*: Creates a new record. If the form needs any special parameter via SIP or Client (=browser), hide this 'new' button - the necessary parameter are not provided.
* *delete*: This either deletes the current record only, or (if defined via action *FormElement* 'beforeDelete' ) any specified subrecords.

Carsten Rose
committed
* *close*: Close the current form. If there are changes, a popup opens and ask to save / close / cancel. The last page from the history will be shown.
* *save*: Save the form.
* Default: show all buttons.

Carsten Rose
committed
.. _`form-forward`:
Forward: Save / Close
^^^^^^^^^^^^^^^^^^^^^

Carsten Rose
committed
Forward (=forwardMode)

Carsten Rose
committed
""""""""""""""""""""""

Carsten Rose
committed
After the user presses *Save*, *Close*, *Delete* or *New*, different actions are possible where the browser redirects to.

Carsten Rose
committed
* `auto` (default) - the QFQ browser Javascript logic, decides to stay on the page or to force a redirection
to a previous page. The decision depends on:

Carsten Rose
committed
* *Close* goes back (feels like close) to the previous page. Note: if there is no history, QFQ won't close the tab,

Carsten Rose
committed
instead a message is shown.

Carsten Rose
committed
* *Save* stays on the current page.

Carsten Rose
committed
* `close` - goes back (feels like close) to the previous page. Note: if there is no history, QFQ won't close the tab,

Carsten Rose
committed
instead a message is shown.
* `no` - no change, the browser remains on the current side. Close does not close the page. It just triggers a save if

Carsten Rose
committed
* `url` - the browser redirects to the URL or T3 page named in `Forward URL / Page`. Independent if the user presses `save` or `close`.

Carsten Rose
committed
* `url-skip-history` - same as `url`, but the current location won't saved in the browser history.

Carsten Rose
committed
* `url-sip` - like `url`, but any given parameter will be SIP encoded. Only useful if `url` points to current web instance.
* `url-sip-skip-history` - like `url-sip`, but skips the Browser history.

Carsten Rose
committed
Only with `Forward` == `url` | `url-skip-history`, the definition of `Forward URL / Page` becomes active.

Carsten Rose
committed
Forward URL / Page (=forwardPage)

Carsten Rose
committed
"""""""""""""""""""""""""""""""""

Carsten Rose
committed

Carsten Rose
committed
Format: [<url>] or [<mode>|<url>]

Carsten Rose
committed
* `<url>`:

Carsten Rose
committed
* `http://www.example.com/index.html?a=123#bottom`
* `website.html?a=123#bottom`
* `?id=<T3 Alias pageid>&a=123#bottom, ?id=<T3 page id>&a=123#bottom`

Carsten Rose
committed
* `{{SELECT ...}}`
* `<mode>|<url>`
* `<mode>` - Valid keywords are as above: `auto|close|no|url|url-skip-history|url-sip|url-sip-skip-history`

Carsten Rose
committed
Specifying the mode in `forwardPage` overwrites `formMode` (but only if `formMode` is `url...`).
Also regular QFQ statements like {{var}} or {{SELECT ...}} are possible in `forwardPage`. This is useful to dynamically
redirect to different targets, depending on user input or any other dependencies.

Carsten Rose
committed
If a forwardMode 'url...' is specified and there is no `forwardPage`, QFQ falls down to `auto` mode.

Carsten Rose
committed
On a form, the user might click 'save' or 'save,close' or 'close' (with modified data this leads to 'save,close').
The CLIENT `submit_reason` shows the user action:
* `{{submit_reason:CE:alnumx}}` = `save` or `save,close`

Carsten Rose
committed
Example forwardPage
^^^^^^^^^^^^^^^^^^^

Carsten Rose
committed
* `{{SELECT IF('{{formModeGlobal:S}}'='requiredOff', 'no', 'auto') }}`

Carsten Rose
committed
* `{{SELECT IF('{{submit_reason:CE:alnumx}}'='save', 'no', 'url'), '|http://example.com' }}`
Type: combined dynamic mode & URL/page
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Syntax: `forwardPage=<mode>|<page>`

Carsten Rose
committed
* `forwardPage={{SELECT IF(a.url='','no','url'), '|', a.url FROM address AS a }}`

Carsten Rose
committed

Carsten Rose
committed
.. _form-parameter:
Parameter

Carsten Rose
committed
^^^^^^^^^
* The following parameter are optional and can be configured in the *Form.parameter* field.

Carsten Rose
committed
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| Name | Type | Description |
+=============================+========+==========================================================================================================+

Carsten Rose
committed
| dbIndex | int | Database credential index, given via `config-qfq-php`_ to let the current `Form` operate on the database.|
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+

Carsten Rose
committed
| bsColumns | string | Wrap the whole form in '<div class="col-md-.. col-lg-..">. See `bs-custom-field-width`_. |

Carsten Rose
committed
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| maxVisiblePill | int | Show pills upto <maxVisiblePill> as button, all further in a drop-down menu. Eg.: maxVisiblePill=3. |

Carsten Rose
committed
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| class | string | HTML div with given class, surrounding the whole form. Eg.: class=container-fluid. |

Carsten Rose
committed
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| classTitle | string | CSS class inside of the `title` div. Default 'qfq-form-title'. |
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+

Carsten Rose
committed
| classPill | string | HTML div with given class, surrounding the `pill` title line. |
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| classBody | string | HTML div with given class, surrounding all *FormElement*. |
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| extraDeleteForm | string | Name of a form which specifies how to delete the primary record and optional slave records. |

Carsten Rose
committed
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| data-pattern-error | string | Pattern violation: Text for error message used for all FormElements of current form. |

Carsten Rose
committed
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| data-required-error | string | Required violation: Text for error message used for all FormElements of current form. |

Carsten Rose
committed
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| data-match-error | string | Match violation: Text for error message used for all FormElements of current form. |

Carsten Rose
committed
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| data-error | string | If none specific is defined: Text for error message used for all FormElements of current form. |

Carsten Rose
committed
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| buttonOnChangeClass | string | Color for save button after user modified some content or current form. E.g.: 'btn-info alert-info'. |

Carsten Rose
committed
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| ldapServer | string | FQDN Ldap Server. E.g.: directory.example.com. |

Carsten Rose
committed
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| ldapBaseDn | string | E.g.: `ou=Addressbook,dc=example,dc=com`. |

Carsten Rose
committed
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| ldapAttributes | string | List of attributes to fill STORE_LDAP with. E.g.: cn, email. |

Carsten Rose
committed
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| ldapSearch | string | E.g.: `(mail={{email::alnumx:l}})` |
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| ldapTimeLimit | int | Maximum time to wait for an answer of the LDAP Server. |

Carsten Rose
committed
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| typeAheadLdap | | Enable LDAP as 'Typeahead' data source. |

Carsten Rose
committed
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| typeAheadLdapSearch | string | Regular LDAP search expression. E.g.: `(|(cn=*?*)(mail=*?*))` |

Carsten Rose
committed
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| typeAheadLdapValuePrintf | string | Value formatting of LDAP result, per entry. E.g.: `'%s / %s / %s', mail, roomnumber, telephonenumber` |
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| typeAheadLdapIdPrintf | string | Key formatting of LDAP result, per entry. E.g.: `'%s', mail` |
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| typeAheadLdapSearchPerToken | | Split search value in token and OR-combine every search with the individual tokens. |

Carsten Rose
committed
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| typeAheadLimit | int | Maximum number of entries. The limit is applied to the server (LDAP or SQL) and the Client. |

Carsten Rose
committed
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| typeAheadMinLength | int | Minimum number of characters which have to typed to start the search. |
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| mode | string | The value `readonly` will activate a global readonly mode of the form - the user can't change any data. |

Carsten Rose
committed
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| enterAsSubmit | digit | 0: off, 1: Pressing *enter* in a form means *save* and *close*. Takes default from configuration_. |
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| submitButtonText | string | Show a save button at the bottom of the form, with <submitButtonText> . See `submitButtonText`_. |
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| saveButtonActive | | 0: off, 1: Make the 'save'-button active on *Form* load (instead of waiting for the first user change). |
| | | The save button is still 'gray' (record not dirty), but the user can click 'save'. |

Carsten Rose
committed
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| saveButtonText | string | Overwrite default from configuration_ |
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| saveButtonTooltip | string | Overwrite default from configuration_ |
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| saveButtonClass | string | Overwrite default from configuration_ |
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| saveButtonGlyphIcon | string | Overwrite default from configuration_ |
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| closeButtonText | string | Overwrite default from configuration_ |
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| closeButtonTooltip | string | Overwrite default from configuration_ |
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| closeButtonClass | string | Overwrite default from configuration_ |
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| closeButtonGlyphIcon | string | Overwrite default from configuration_ |
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| deleteButtonText | string | Overwrite default from configuration_ |
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| deleteButtonTooltip | string | Overwrite default from configuration_ |
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| deleteButtonClass | string | Overwrite default from configuration_ |
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| deleteButtonGlyphIcon | string | Overwrite default from configuration_ |
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| newButtonText | string | Overwrite default from configuration_ |
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| newButtonTooltip | string | Overwrite default from configuration_ |
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| newButtonClass | string | Overwrite default from configuration_ |
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| newButtonGlyphIcon | string | Overwrite default from configuration_ |
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| extraButtonInfoClass | string | Overwrite default from configuration_ |

Carsten Rose
committed
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| extraButtonInfoMinWidth | string | See extraButtonInfo_ |
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| fillStoreVar | string | Fill the STORE_VAR with custom values. See `STORE_VARS`_. |
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| showIdInFormTitle | string | Overwrite default from configuration_ |
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
Elias Villiger
committed
| formSubmitLogMode | string | Overwrite default from configuration_ |
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+

Carsten Rose
committed
| sessionTimeoutSeconds | int | Overwrite default from configuration_ . See sessionTimeoutSeconds_. |
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+

Carsten Rose
committed
| maxFileSize | int | Overwrite default from configuration_ . |
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+

Carsten Rose
committed
| requiredPosition | int | See requiredPosition_ . |
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+

Carsten Rose
committed
| minWidth | int | See checkboxRadioMinWidth_ . |
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+

Carsten Rose
committed

Carsten Rose
committed

Carsten Rose
committed
* Example:
* maxVisiblePill = 5
* class = container-fluid
* classBody = qfq-form-right
.. _submitButtonText:

Carsten Rose
committed
submitButtonText

Carsten Rose
committed
""""""""""""""""

Carsten Rose
committed
If specified and non empty, display a regular submit button at the bottom of the page with the given text.
This gives the form a ordinary HTML-form look'n' feel. With this option, the standard buttons on the top right border
should be hided to not confuse the user.

Carsten Rose
committed
* Optional.
* Default: Empty
class

Carsten Rose
committed
"""""

Carsten Rose
committed
* Optional.
* Default: `container`
* Any CSS class name(s) can be specified.
* Check `typo3conf/ext/qfq/Resources/Public/Css/qfq-bs.css` for predefined classes.
* Typical use: adjust the floating rules of the form.
* See: http://getbootstrap.com/docs/3.4/css/#overview-container

Carsten Rose
committed
* Expand the form over the whole area: `container-fluid`
classPill

Carsten Rose
committed
"""""""""

Carsten Rose
committed
* Optional.
* Default: `qfq-color-grey-1`
* Any CSS class name(s) can be specified.
* Check `typo3conf/ext/qfq/Resources/Public/Css/qfq-bs.css` for predefined classes.
* Typical use: adjust the background color of the `pill title` area.
* Predefined background colors: `qfq-color-white`, `qfq-color-grey-1` (dark), `qfq-color-grey-2` (light),
`qfq-color-blue-1` (dark), `qfq-color-blue-2`. (light)
* `classPill` is only visible on forms with container elements of type 'Pill'.

Carsten Rose
committed
classBody

Carsten Rose
committed
"""""""""

Carsten Rose
committed
* Optional.
* Default: `qfq-color-grey-2`
* Any CSS class name(s) can be specified.
* Check `typo3conf/ext/qfq/Resources/Public/Css/qfq-bs.css` for predefined classes.
* Typical use:
* adjust the background color of the *FormElement* area.
* make all form labels right align: `qfq-form-right`.
* Predefined background colors: `qfq-color-white`, `qfq-color-grey-1` (dark), `qfq-color-grey-2` (light),
`qfq-color-blue-1` (dark), `qfq-color-blue-2`. (light)
extraDeleteForm

Carsten Rose
committed
"""""""""""""""

Carsten Rose
committed
Depending on the database definition, it might be necessary to delete the primary record *and* corresponding slave records.
To not repeat such 'slave record delete definition', an 'extraDeleteForm' can be specified. If the user opens a record
in a form and clicks on the 'delete' button, a defined 'extraDeleteForm'-form will be used to delete primary and slave
records instead of using the current form.
E.g. if there are multiple different forms to work on the same table, all of theses forms might reference to the same
'extraDeleteForm'-form. This simplifies the maintenance.
The 'extraDeleteForm' parameter might be specified for a 'form' and/or for 'subrecords'

Carsten Rose
committed
""""""""""""""""
A form can be operated in modes: *standard* | **readonly** | **requiredOff** | **requiredOffButMark**.
Mode *standard* is given if none of the others are defined.
The `mode` is given via (in this priority):
* Via STORE_USER: {{formModeGlobal:U}}
* Via STORE_SIP: {{formModeGlobal:S}}
* Via Form: `form.parameter.mode=...`
Mode
;;;;
* *standard*:

Carsten Rose
committed
* The form will behave like defined in the form editor.
* Missing required values will a) be indicated and b) block saving the record.
* **readonly**: all `FormElement` of the whole form are temporarily in `readonly` mode.
* Fast way to display the form data, without a possibility for the user to change any data of the form.
* The mode will be be inherited to all subforms.
* **requiredOff**:

Carsten Rose
committed
* All `FormElement` with `mode=required`, will be handled as `mode=show`.
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
* The user can save the form without filling all required inputs!
* Required inputs are indicated by a red star - missing values **won't** be complained.
* **requiredOffButMark**:
* All `FormElement` with `mode=required`, will be handled as `mode=show`.
* The user can save the form without filling all required inputs!
* Missing required inputs will be marked:
* On lost focus.
* When the user saves the record.
Extra
;;;;;
Via `STORE_VARS`_ the variable `{{allRequiredGiven:V}}` shows, if the form has been filled completely - independent of
the mode. The variable is only accessible during form save.
Usage example
;;;;;;;;;;;;;
*Readonly*
Code: ``SELECT 'p:{{pageAlias}}&form=person&r=1&formModeGlobal=readonly|s|t:View|s|b' AS _link``
* The form is called with SIP parameter ``formModeGlobal=readonly`` or ``form.parameter.mode=readonly``.
* The user can't change any data.
*Readonly systemwide*
Code (somewhere): ``SELECT 'requiredoff' AS '_=formModeGlobal'``
Code: ``SELECT 'p:{{pageAlias}}&form=person&r=1|s|t:View|s|b' AS _link``
* The STORE_USER variable is set `formModeGlobal=readonly`.
* All forms will be shown in readonly mode - fast option to give a user access to the website, without the possibility to
change any data.

Carsten Rose
committed
*Draft Mode 1*

Carsten Rose
committed
Code: ``SELECT 'p:{{pageAlias}}&form=person&r=1&formModeGlobal=readquiredOff|s|t:View|s|b' AS _link``

Carsten Rose
committed
* A form has one or more FormElement with 'fe.type=required'.
* Opening the form with `formModeGlobal=requiredOff` will allow the user to save the form, even if not all
FE.type=required elements are given. This can be called 'draft' mode.
* Opening the form without `formModeGlobal` (that's the default), forces the user to fill out
all FE.type=required fields. This can be called 'final submit' mode.

Carsten Rose
committed
*Draft Mode 2*

Carsten Rose
committed
Code: ``SELECT 'p:{{pageAlias}}&form=person&r=1&formModeGlobal=readquiredOff|s|t:View|s|b' AS _link``

Carsten Rose
committed
* A form has one or more FormElement with 'fe.type=required'.
* Calling the form with `formModeGlobal=requiredOff` will allow the user to save the form, even if not all
FE.type=required elements are given.
* Define an FE-Action 'afterSave', and do some action on `{{allRequiredGiven:V0}}` like::

Carsten Rose
committed
{{UPDATE <table> SET dataValid={{allRequiredGiven:V0}} WHERE id={{id:R}} }}
* In the application logic, open the next process step if all data is given by evaluating `dataValid`.

Carsten Rose
committed
FormElements
------------
* Each *form* contains one or more *FormElement*.
* The *FormElements* are divided in three categories:

Carsten Rose
committed
* `class-container`_
* `class-native`_
* `class-action`_

Carsten Rose
committed
* Ordering and grouping: Native *FormElements* and Container-Elements (both with feIdContainer=0) will be ordered by 'ord'.
* Inside of a container, all nested elements will be displayed.
* Technical, it's *not* necessary to configure a FormElement for the primary index column `id`.
* Additional options to a *FormElement* will be configured via the *FormElement.parameter* field (analog to *Form.parameter*
for *Forms* ).

Carsten Rose
committed
* See also: `comment-space-character`_

Carsten Rose
committed
.. _class-container:
Class: Container
----------------
* Pills are containers for 'fieldset' *and* / *or* 'native' *FormElements*.
* Fieldsets are containers for 'native' *FormElements*.
* TemplateGroups are containers for 'fieldset' *and* / *or* 'native' *FormElements*.
Type: fieldset
^^^^^^^^^^^^^^
* Native *FormElements* can be assigned to a fieldset.
* FormElement settings:
* *name*: technical name, used as HTML identifier.
* *label*: Shown title of the fieldset.
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
Type: pill (tab)
^^^^^^^^^^^^^^^^
* Pill is synonymous for a tab and looks like a tab.
* If there is at least one pill defined:
* every native *FormElement* needs to be assigned to a pill or to a fieldset.
* every *fieldset* needs to be assigned to a pill.
* Mode:
* `show`: all child elements will be shown.
* `required`: same as 'show'. This mode has no other meaning than 'show'.
* `readonly`: technical it's like HTML/CSS `disabled`.
* The pill title is shown, but not clickable.
* The `FormElements` on the pill still exist, but are not reachable for the user via UI.
* `hidden`:
* The pill is invisible.
* The `FormElements` on the pill still exist, but are not reachable for the user via UI.
* Note: Independent of the *mode*, all child elements are always rendered and processed by the client/server.

Carsten Rose
committed
* Pills are 'dynamicUpdate' aware. `title` and `mode` are optional recalculated during 'dynamicUpdate'.

Carsten Rose
committed
* FormElement settings:
* *name*: technical name, used as HTML identifier.
* *label*: Label shown on the corresponding pill button or inside the drop-down menu.

Carsten Rose
committed
* *mode*:
* *show*, *required*: regular mode. The pill will be shown.
* *readonly*: the pill and it's name is visible, but not clickable.
* *hidden*: the pill is not shown at all.
* *modeSql*:

Carsten Rose
committed
* *type*: *pill*
* *feIdContainer*: `0` - Pill's can't be nested.
* *tooltip*: Optional tooltip on hover. Especially helpful if the pill is set to *readonly*.

Carsten Rose
committed
* *parameter*:
* *maxVisiblePill*: `<nr>` - Number of Pill-Buttons shown. Undefined means unlimited. Excess Pill buttons will be

Carsten Rose
committed
Type: templateGroup
^^^^^^^^^^^^^^^^^^^
*TemplateGroups* will be used to create a series of grouped (by the given *templateGroup*) *FormElements*.
*FormElements* can be assigned to a *templateGroup*. These *templateGroup* will be rendered upto *n*-times. On 'form load'

Carsten Rose
committed
only a single (=first) copy of the *templateGroup* will be shown. Below the last copy of the *templateGroup* an 'add'-button is
shown. If the user click on it, an additional copy of the *templateGroup* is displayed. This can be repeated up to
*templateGroup.maxLength* times. Also, the user can 'remove' previously created copies by clicking on a remove button near
beside every *templateGroup*. The first copy of a templateGroup can't be removed.
* FormElement settings:
* *label*: Shown in the FormElement-editor *container* field.
* *maxLength*: Maximum number of copies of the current *templateGroup*. Default: 5.
* *bsLabelColumn*, *bsInputColumn*, *bsNoteColumn*: column widths for row with the 'Add' button.
* *parameter*:
* *tgAddClass*: Class of the 'add' button. Default: `btn btn-default`.
* *tgAddText*: Text shown on the button. Default: `Add`.
* *tgRemoveClass*: Class of the 'remove' button. Default: `btn btn-default`.
* *tgRemoveText*: Text shown on the button. Default: `Remove`.
* *tgClass*: Class wrapped around every copy of the *templateGroup*.
E.g. the class `qfq-child-margin-top` adds a margin between two copies of the *templateGroup*. Default: empty

Carsten Rose
committed
Multiple *templateGroups* per form are allowed.
The name of the native FormElements, inside the templateGroup, which represents the effective table columns, uses the placeholder
`%d`. E.g. the columns `grade1`, `grade2`, `grade3` needs a *FormElement.name* = `grade%d`. The counting will always start with 1.
The placeholder `%d` can also be used in the *FormElement.label*
Example of styling the Add/ Delete Button: :ref:`example_class_template_group`
Column: primary record

Carsten Rose
committed
""""""""""""""""""""""
If the columns `<name>%d` are real columns on the primary table, saving and delete (=empty string) are done automatically.
E.g. if there are up to five elements `grade1, ..., grade5` and the user inputs only the first three, the remaining will be set
to an empty string.
Column: non primary record

Carsten Rose
committed
""""""""""""""""""""""""""
Additional logic is required to load, update, insert and/or delete slave records.
Load
;;;;
On each native *FormElement* of the *templateGroup* define an SQL query in the *FormElement.value* field. The query has to
select **all** values of all possible existing copies of the *FormElement* - therefore the exclamation mark is necessary.
Also define the order. E.g. *FormElement.value*::
{{!SELECT street FROM Address WHERE personId={{id}} ORDER BY id}}
Insert / Update / Delete
;;;;;;;;;;;;;;;;;;;;;;;;
Add an *action* record, type='afterSave', and assign the record to the given *templateGroup*.
In the parameter field define: ::
slaveId = {{SELECT id FROM Address WHERE personId={{id}} ORDER BY id LIMIT %D,1}}
sqlHonorFormElements = city%d, street%d
sqlUpdate = {{UPDATE Address SET city='{{city%d:FE:alnumx:s}}', street='{{street%d:FE:alnumx:s}}' WHERE id={{slaveId}} LIMIT 1}}
sqlInsert = {{INSERT INTO Address (`personId`, `city`, `street`) VALUES ({{id}}, '{{city%d:FE:alnumx:s}}' , '{{street%d:FE:alnumx:s}}') }}
sqlDelete = {{DELETE FROM Address WHERE id={{slaveId}} LIMIT 1}}
The `slaveId` needs attention: the placeholder `%d` starts always at 1. The `LIMIT` directive starts at 0 - therefore
use `%D` instead of `%d`, cause `%D` is always one below `%d` - but can **only** be used on the action element.

Carsten Rose
committed
.. _class-native:

Carsten Rose
committed
Class: Native
-------------
Fields:

Carsten Rose
committed
+---------------------+-----------------------------+-----------------------------------------------------------------------------------------------------+
| Name | Type | Description |
+=====================+=============================+=====================================================================================================+
|Container | int | 0 or *FormElement*.id of container element (pill, fieldSet, templateGroup) part the current *Form* |
+---------------------+-----------------------------+-----------------------------------------------------------------------------------------------------+
|Enabled | enum('yes'|'no') | Process the current FormElement |
+---------------------+-----------------------------+-----------------------------------------------------------------------------------------------------+
|Dynamic Update | enum('yes'|'no') | In the browser, *FormElements* with "dynamicUpdate='yes'" will be updated depending on user |
| | | input. :ref:`dynamic-update` |
+---------------------+-----------------------------+-----------------------------------------------------------------------------------------------------+
|Name | string | |
+---------------------+-----------------------------+-----------------------------------------------------------------------------------------------------+
|Label | string | Label of *FormElement*. Depending on layout model, left or on top of the *FormElement* |
| | | Additional label description can be added by wrapping in HTML tag '<small>' |

Carsten Rose
committed
+---------------------+-----------------------------+-----------------------------------------------------------------------------------------------------+
|Mode | enum('show', 'readonly', | | *Show*: regular user input field. This is the default. |
| | 'required', | | *Required*: User has to specify a value. Typically, an <empty string> represents 'no value'. |
| | 'hidden' ) | | *Readonly*: User can't change. Data is not saved, except for FormElement with 'processReadOnly' |
| | | | *Hidden*: *FormElement* is not visible. |

Carsten Rose
committed
+---------------------+-----------------------------+-----------------------------------------------------------------------------------------------------+
|Mode sql | `SELECT` statement with | A value given here overwrites the setting from `mode`. Most useful with :ref:`dynamic-update`. |

Carsten Rose
committed
| | a value like in `mode` | E.g.: {{SELECT IF( '{{otherFunding:FR:alnumx}}'='yes' ,'show', 'hidden' }} |
+---------------------+-----------------------------+-----------------------------------------------------------------------------------------------------+
|Class | enum('native', 'action', | Details below. |
| | 'container') | |
+---------------------+-----------------------------+-----------------------------------------------------------------------------------------------------+

Carsten Rose
committed
|Type | enum('checkbox', 'date', 'time', 'datetime', 'dateJQW', 'datetimeJQW', 'extra', 'gridJQW', 'text', 'editor', 'annotate', |
| | 'imageCut', 'note', 'password', 'radio', 'select', 'subrecord', 'upload', 'fieldset', 'pill', 'beforeLoad', 'beforeSave', |

Carsten Rose
committed
| | 'beforeInsert', 'beforeUpdate', 'beforeDelete', 'afterLoad', 'afterSave', 'afterInsert', 'afterUpdate', 'afterDelete', |
| | 'sendMail') |
+---------------------+-----------------------------+-----------------------------------------------------------------------------------------------------+
|Encode | 'none', 'specialchar' | With 'specialchar' (default) the chars <>"'& will be encoded to their htmlentity. _`field-encode` |

Carsten Rose
committed
+---------------------+-----------------------------+-----------------------------------------------------------------------------------------------------+
|Check Type | enum('auto', 'alnumx', | See: `sanitize-class`_ |
| | 'digit', 'numerical', | |
| | 'email', 'pattern', | |
| | 'allbut', 'all') | |

Carsten Rose
committed
+---------------------+-----------------------------+-----------------------------------------------------------------------------------------------------+
|Check Pattern | 'regexp' | _`field-checktype`: If $checkType=='pattern': pattern to match |

Carsten Rose
committed
+---------------------+-----------------------------+-----------------------------------------------------------------------------------------------------+
|Order | string | Display order of *FormElements* ('order' is a reserved keyword) _`field-ord` |

Carsten Rose
committed
+---------------------+-----------------------------+-----------------------------------------------------------------------------------------------------+
|labelAlign | left | Label align (default/left/center/right)/ Default: 'default' (defined by Form). |

Carsten Rose
committed
+---------------------+-----------------------------+-----------------------------------------------------------------------------------------------------+
|Size | string | Depends on the FormElement type. E.g. visible length (and height) of input element `input-text`_ . |
| | | Might be omitted, depending on the chosen form layout. |

Carsten Rose
committed
| | | Format: <width>[,<(min) height>[,<max height]] (in characters). |

Carsten Rose
committed
+---------------------+-----------------------------+-----------------------------------------------------------------------------------------------------+

Carsten Rose
committed
|BS Label Columns | string | Number of bootstrap grid columns. By default empty, value inherits from the form. |
| | | _`field-bsLabelColumns`. See `bs-custom-field-width`_ |
+---------------------+-----------------------------+ |
|BS Input Columns | string | |
+---------------------+-----------------------------+ |
|BS Note Columns | string | |

Carsten Rose
committed
+---------------------+-----------------------------+-----------------------------------------------------------------------------------------------------+
|Label / Input / Note | enum(...) | Switch on/off opening|closing of bootstrap form classes _`field-rowLabelInputNote` |

Carsten Rose
committed
+---------------------+-----------------------------+-----------------------------------------------------------------------------------------------------+