Form¶
- Forms will be created by using the QFQ Form Editor on the Typo3 frontend (HTML form).
- The Formeditor itself consist of two predefined QFQ forms: form and formElement
- 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.
- There are three types of forms which can roughly categorized into:
- 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 addNupdate records.
- Multi form: the form acts simultanously on more than one record. All records use the same FormElements.
- The FormElements are defined as a regular simple / or advanced form, plus a SQL Query, which selects and iterates over all records. Those records will be loaded at the same time.
- Simple form: the form acts on one record, stored in one table.
Definition¶
Name | Type | Description |
---|---|---|
id | int, autoincrement | created by by MySQL |
name | string | unique and speaking name of the form. Form will be identified by this name |
title | string | Title, shown on/above the form. |
noteInternal | textarea | Internal notes: special functionality, used variables, ... |
tableName | string | Primay table of the form |
permitNew | enum(‘sip’, ‘logged_in’, ‘logged_out’, ‘always’, ‘never’) | Default: sip |
permitEdit | enum(‘sip’, ‘logged_in’, ‘logged_out’, ‘always’, ‘never’) | Default: sip |
render | enum(‘plain’,’table’, ‘bootstrap’) | Default bootstrap |
requiredParameter | string | Name of required SIP parameter, seperated by comma. ‘#’ as comment delimiter |
showButton | set(‘new’, ‘delete’, ‘close’, ‘save’) | Default ‘new,delete,close,save’. Shown buttons in the upper right corner of the form. |
multiMode | enum(‘none’,’horizontal’,’vertical’) | Default ‘none’ |
multiSql | text | Optional. SQL Query which selects all records to edit. |
multiDetailForm | string | Optional. Form to open, if a record is selected to edit (double click on record line) |
multiDetailFormParameter | string | Optional. Translated Parameter submitted to detailform (like subrecord parameter) |
forwardMode | string: ‘auto | no | page’ | |
forwardPage | string / query | If $forward==”page”: page to jump to |
bsLabelColumns | string | 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 for all FormElements. Exceptions per FormElement can be specified per FormElement. Default: label=3, input=6, note=3. See Form Layout. |
bsInputColumns | string | |
bsNoteColumns | string | |
parameter | text | Misc additional parameters. See parameter. |
deleted | string | ‘yes’|’no’. |
modified | timestamp | updated automatically through stored procedure |
created | datetime | set once through QFQ |
showButton¶
Display or hide the button new, delete, close, save.
- new: Creates a new record. If the form needs any special parameter via SIP or Client, hide this ‘new’ button - the necessary parameter are not provided.
- delete: This either deletes the current record only, or (if defined via action FormElement ‘before Delete’ ) any specified subrecords.
- 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.
parameter¶
- The following parameter are optional and can be configured in the Form.parameter field.
- Comments: lines starting with a ‘#’ are treated as a comment and will not be parsed.
Name | Type | Description |
---|---|---|
maxVisiblePill | int | Show pills upto <maxVisiblePill> as button, all further in a dropdown menu. Eg.: maxVisiblePill=3 |
class | string | HTML div with given class, surrounding the whole form. Eg.: class=container-fluid |
classPill | string | HTML div with given class, surrounding the pill title line. |
classBody | string | HTML div with given class, surrounding all FormElement. |
submitButtonText | string | Show save button, with the <submitButtonText> at the bottom of the form |
extraDeleteForm | string | Name of a form which specifies how to delete the primary record and optional slave records |
data-pattern-error | string | Pattern violation: Text for error message used for all FormElements of current form |
data-required-error | string | Required violation: Text for error message used for all FormElements of current form |
data-match-error | string | Match violation: Text for error message used for all FormElements of current form |
data-error | string | If none specific is defined: Text for error message used for all FormElements of current form |
buttonOnChangeClass | string | Color for save button after user modified some content or current form. E.g.: ‘btn-info alert-info’ |
- Example:
- maxVisiblePill = 5
- class = container-fluid
- classBody = qfq-form-right
submitButtonText¶
- Optional.
- Default: Empty
- Empty: a ‘submit’ button with a Bootstrap glyph ‘check’ symbol is rendered at the top right corner of the form.
- Non Empty: a ‘submit’ button, with <submitButtonText>, is rendered at the bottom of the form (without a ‘check’ glyph symbol). Typically ‘ShowButton: Save’ will be unchecked to hide the regular save glyph symbol.
class¶
- 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/css/#overview-container * Expand the form over the whole area: container-fluid
classPill¶
- 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 elemants of type ‘Pill’.
classBody¶
- 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)
submitButtonText¶
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.
extraDeleteForm¶
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’
FormElements¶
- Each form contains one or more FormElement.
- The FormElements are divided in three categories:
- 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 ).
- Comments: lines starting with a ‘#’ are treated as a comment and will not be parsed.
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.
Type: pill¶
- Pill is synonymous for a tab. A pill looks like a tab.
- Pills are only available with mode render=’bootstrap’.
- If there is at least one pill defined, every native FormElement needs to be assigned to a pill or to a fieldset.
- If there is at least one pill defined, every fieldset needs to be assigned to a pill.
- FormElement settings:
- name: technical name, used as HTML identifier.
- label: Label shown on the corresponding pill button or inside the dropdown menu.
- type: pill
- feIdContainer: 0 - Pill’s can’t be nested.
- parameter:
- maxVisiblePill: <nr> - Number of Pill-Buttons shown. Undefined means unlimited. Excess Pill buttons will be displayed as a dropdown menu.
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’ 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
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
Class: Native¶
Fields:
Name | Type | Description |
---|---|---|
id | int | |
formId | int | |
feIdContainer | int | |
enabled | enum(‘yes’|’no’) | |
dynamicUpdate | enum(‘yes’|’no’) | In the browser, FormElements with “dynamicUpdate=’yes’” will be updated depending on user input. Dynamic Update |
name | string | |
label | string | Label of FormElement. Depending on layout model, left or on top of the FormElement |
mode | enum(‘show’, ‘readonly’, ‘required’, ‘disabled’ ) | Show: regular user input field. This is the default. Required: User has to specify a value. Typically, an <empty string> represents ‘no value’. Readonly: user can’t change any data. Data not saved. Disabled: FormElement is not visible. |
modeSql | select statement with a value like in mode | A value given here overwrites the setting from mode. Most usefull with Dynamic Update. E.g.: {{SELECT IF( ‘{{otherFunding:FR:alnumx}}’=’yes’ ,’show’, ‘hidden’ }} |
class | enum(‘native’, ‘action’, ‘container’) | Details below. |
type | enum(‘checkbox’, ‘date’, ‘time’, ‘datetime’, ‘dateJQW’, ‘datetimeJQW’, ‘extra’, ‘gridJQW’, ‘text’, ‘editor’, ‘note’, ‘password’, ‘radio’, ‘select’, ‘subrecord’, ‘upload’, ‘fieldset’, ‘pill’, ‘beforeLoad’, ‘beforeSave’, ‘beforeInsert’, ‘beforeUpdate’, ‘beforeDelete’, ‘afterLoad’, ‘afterSave’, ‘afterInsert’, ‘afterUpdate’, ‘afterDelete’, ‘sendMail’) | |
checkType | enum(‘min|max’, ‘pattern’, ‘number’, ‘email’) | |
checkPattern | ‘regexp’ | If $checkType==’pattern’: pattern to match |
onChange | string |
|
ord | string | Display order of FormElements (‘order’ is a reserved keyword) |
tabindex | string | HTML tabindex attribute |
size | string | Visible length of input element. Might be ommited, depending on the choosen form layout. Format: <width>,<height> (in characters) |
bsLabelColumns | string | Number of bootstrap grid columns for label. By default empty, value inherits from the form. |
bsInputColumns | string | Number of bootstrap grid columns for input. By default empty, value inherits from the form. |
bsNoteColumns | string | Number of bootstrap grid columns for note. By default empty, value inherits from the form. |
maxLength | string | Maximum characters for input. |
note | string | Note of FormElement. Depending on layout model, right or below of the FormElement. |
tooltip | text | Display this text as tooltip on mouse over. |
placeholder | string | Text, displayed inside the input element in light grey. |
clientJs | text | Javascript called on ‘on change’ FormElement |
value | text | Default value |
sql1 | text | SQL query |
parameter | text | Might contain misc parameter. Depends on the type of FormElement. |
feGroup | string | Comma-separated list of Typo3 FE Group ID. NOT SURE IF THIS WILL BE IMPLEMENTED. Native FormElements, fieldsets and pills can be assigned to feGroups. Group status: show, hidden, disabled. Group Access: FE-Groups. User will be assigned to FE-Groups and the form definition reference such FE-groups. Easy way of granting permission. |
deleted | string | ‘yes’|’no’. |
modified | timestamp | updated automatically through stored procedure |
created | datetime | set once through QFQ |
Attributes defined in the parameter field¶
See also at specific FormElement definitions.
Name | Type | Note |
data-pattern-error | string | Pattern violation: Text for error message used for all FormElements of current form |
data-required-error | string | Required violation: Text for error message used for all FormElements of current form |
data-match-error | string | Match violation: Text for error message used for all FormElements of current form |
data-error | string | If none specific is defined: Text for error message used for all FormElements of current form |
htmlBefore | string | HTML Code wrapped before the complete FormElement |
htmlAfter | string | HTML Code wrapped after the complete FormElement |
wrapRow | string | If specified, skip default wrapping (<div class=’col-md-?>). Instead the given string is used. |
wrapInput | string | |
wrapInput | string | |
wrapNote | string |
Effect matrix¶
Attribute | checkbox | dateJQW | datetimeJQW | gridJQW | extra | text | note | password | radio | select | subrecord | timeJQW | upload | editor |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
id | Internal id | |||||||||||||
formId | Form | |||||||||||||
containerId | Assign the FormElement to user defined fieldSet or pill | |||||||||||||
enabled | FormElement is active or not | |||||||||||||
name | Name of a column of the primary table. FormElements with a corresponding table will be saved automatically. | |||||||||||||
label | Label shown to the user. | |||||||||||||
mode | show, readonly, required, lock, disable. | |||||||||||||
class | native | |||||||||||||
type | checkbox | dateJQW | datetimeJQW | gridJQW | extra | text | note | password | radio | select | subrecord | timeJQW | upload | |
checkType | ||||||||||||||
checkPattern | ||||||||||||||
onChange | ||||||||||||||
ord | ||||||||||||||
tabindex | ||||||||||||||
size |
|
|
||||||||||||
maxLength | 1 |
|
||||||||||||
note | ||||||||||||||
tooltip | ? | |||||||||||||
placeholder | ||||||||||||||
clientJs | ||||||||||||||
value | ||||||||||||||
sql1 | ? | |||||||||||||
Additional attributes in Field ‘parameter’. Typically in key=value format. | ||||||||||||||
type | checkbox | dateJQW | datetimeJQW | gridJQW | extra | text | note | password | radio | select | subrecord | timeJQW | upload | editor |
accept | ? | |||||||||||||
alt | ? | |||||||||||||
autocomplete | ||||||||||||||
autofocus | ||||||||||||||
checkBoxMode | ||||||||||||||
checked | ||||||||||||||
unchecked | ||||||||||||||
label2 | ||||||||||||||
itemList | ||||||||||||||
emptyItemAtStart | ||||||||||||||
emptyItemAtEnd | ||||||||||||||
emptyHide | ||||||||||||||
retype | ||||||||||||||
accept |
|
|||||||||||||
slaveId | ||||||||||||||
fileDestination | ||||||||||||||
sqlBefore | ||||||||||||||
sqlInsert | ||||||||||||||
sqlDelete | ||||||||||||||
sqlAfter |
- 1: A line break created every <size> elements. Easy way to make checkboxes or radio vertical instead of horizontal.
- 2: Any number >1 makes the ‘select’ input ‘multiple’ ready.
- See: https://www.w3.org/TR/html5/forms.html#file-upload-state-(type=file)
- All ‘native’ FormElements like ‘input’, ‘checkbox’, ...
- ‘autofocus’: The first FormElement with this attribute will get the focus after form load. If there is no such attribute
- given to any FormElement, the attribute will be automatically assigned to the first editable FormElement.
To disable ‘autofocus’ on a form, set ‘autofocus=0’ on the first editable FormElement.
Note: If there are multiple pills defined on a form, only the first pill will be set with ‘autofocus’.
Type: checkbox¶
Checkboxes can be rendered in mode:
single:
- One column in a table corresponds to one checkbox.
- The value for statuses checked and unchecked are free to choose.
- This mode is selected, if a) checkBoxMode = single, or b) checkBoxMode is missing and the number of fields of the column definition is <3.
- FormElement.parameter:
- checkBoxMode = single (optional)
- checked = <value> (optional, the value which represents ‘checked’)
- If checked is empty or missing: If type = ‘enum’ or ‘set’, get first item of the definition. If type = string, get default.
- unchecked = <value> (optional, the value which represents ‘unchecked’)
- If unchecked is empty or missing: If type = ‘enum’ or ‘set’, get second item of checked. If type = ‘string’, get ‘’.
- label2 = <value> (Text right beside checkbox) (optional)
multi:
One column in a table represents multiple checkboxes. This is typically useful for the column type set.
The value for status checked are free to choose, the value for status unchecked is always the empty string.
Each field key (or the corresponding value from the key/value pair) will be rendered right beside the checkbox.
FormElement.parameter
- checkBoxMode: multi
- itemList - E.g.:
itemList=red,blue,orange
itemList=1:red,2:blue,3:orange
itemList={{!SELECT id, value FROM someTable}}
FormElement.maxlength - vertical or horizontal alignment:
- Value: ‘’, 0, 1 - The check boxes will be aligned vertical.
- Value: >1 - The check boxes will be aligned horizontal, with a linebreak every ‘value’ elements.
FormElement.parameter:
- emptyHide: Existence of this item hides an entry with an empty string. This is useful for e.g. Enums, which have an empty entry, but the empty value should not be selectable.
- emptyItemAtStart: Existence of this item inserts an empty entry at the beginning of the selectlist.
- emptyItemAtEnd: Existence of this item inserts an empty entry at the end of the selectlist.
- buttonClass: Instead of the plain HTML checkbox fields, Bootstrap buttons. are rendered as checkbox elements. Use one of the following classes: * btn-default (default, grey), * btn-primary (blue), * btn-success (green), * btn-info (light blue), * btn-warning (orange), * btn-danger (red). With a given buttonClass, all buttons (=radios) are rendered horizontal. A value in FormElement.maxlength has no effect.
No preselection:
If a form is in ‘new’ mode and if there is a default value configured on a table column, such a value is shown by default. There might be situations, where the user should be forced to select a value (e.g. specifying the gender). An unwanted default value can be suppressed by specifying an explicit definition on the FormElement field value:
{{<columnname>:RZ}}
For existing records the shown value is as expected the value of the record. For new records, it’s the value 0, which is typically not one of the ENUM / SET values and therefore nothing is selected.
Type: date¶
- Range datetime: ‘1000-01-01’ to ‘9999-12-31’ or ‘0000-00-00’. (http://dev.mysql.com/doc/refman/5.5/en/datetime.html)
- Optional:
- FormElement.parameter.dateFormat: yyyy-mm-dd | dd.mm.yyyy
Type: datetime¶
- Range datetime: ‘1000-01-01 00:00:00’ to ‘9999-12-31 23:59:59’ or ‘0000-00-00 00:00:00’. (http://dev.mysql.com/doc/refman/5.5/en/datetime.html)
- Optional:
- FormElement.parameter:
- dateFormat: yyyy-mm-dd | dd.mm.yyyy
- showSeconds: 0|1 - shows the seconds. Independent if the user specifies seconds, they are displayed ‘1’ or not ‘0’.
- showZero: 0|1 - For an empty timestamp, With ‘0’ nothing is displayed. With ‘1’ the string ‘0000-00-00 00:00:00’ is displayed.
- FormElement.parameter:
Type: extra¶
- Element is not shown in the browser.
- The element can be used to define / precalculate values for a column, which do not already exist as a native FormElement.
- The element is build / computed on form load and saved alongside with the SIP parameter of the current form.
- Access the value without specifying any store (default store priority is sufficient).
Type: text¶
- General input for text and number.
- FormElement.size:
- <number>: width of input element in characters. Lineheight = 1.
- <cols>,<rows>: input element = textarea, width=<cols>, height=<rows>
- FormElement.parameter:
- retype = 1 (optional): Current input element will be rendered twice. The form can only submitted if both elements are equal.
- retypeLabel =<text> (optional): The label of the second element.
- retypeNote =<text> (optional): The note of the second element.
- Also check the Attributes defined in the parameter field data-...-error to customize error messages shown by the validator.
Type: editor¶
TinyMCE (https://www.tinymce.com, community edition) is used as the QFQ Rich Text Editor.
The content will be saved as HTML inside the database.
All configuration and plugins will be configured via the ‘parameter’ field. Just prepend the word ‘editor-‘ in front of each TinyMCE keyword. Check possible options under https://www.tinymce.com/docs/configure/, https://www.tinymce.com/docs/plugins/, https://www.tinymce.com/docs/advanced/editor-control-identifiers/#toolbarcontrols
Bars:
- Top: menubar - by default hidden.
- Top: toolbar - by default visible.
- Bottom: statusbar - by default hidden, exception: min_height and max_height are given via size parameter.
The default setting in FormElement.parameter is:
editor-plugins=code link searchreplace table textcolor textpattern visualchars editor-toolbar=code searchreplace undo redo | styleselect link table | fontselect fontsizeselect | bullist numlist outdent indent | forecolor backcolor bold italic editor-menubar=false editor-statusbar=false
FormElement.size:
- <min_height>,<max_height>: in pixels, including top and bottom bars. E.g.: 300,600
Type: note¶
An FormElement without any ‘input’ functionality -just to show some text. Use the typical fields ‘label’, ‘value’ and ‘note’ to be displayed in the corresponding three standard columns.
Type: password¶
- Like a text element, but every character is shown as an asterisk.
Type: radio¶
Radio Buttons will be built from one of three sources:
- ‘sql1’: E.g. {{!SELECT type AS label FROM car }} or {{!SELECT type AS label, typeNr AS id FROM car}} or {{!SHOW tables}}.
- Resultset format ‘named’: column ‘label’ and optional a column ‘id’.
- Resultset format ‘index’:
- One column in resultset >> first column represents label
- Two or more columns in resultset >> first column represents id and second column represents label.
- FormElement.parameter:
- itemList = <attribute> E.g.: itemList=red,blue,orange or itemList=1:red,2:blue:3:orange
- Definition of the enum or set field (only labels, ids are not possible).
FormElement.maxlength = <value>
- Applies only to ‘plain’ radio elements (not the Bootstrap ‘buttonClass’ from below)
- vertical or horizontal alignment:
- <value>: ‘’, 0, 1 - The radios will be aligned vertical.
- <value>: >1 - The readios will be aligned horizontal, with a linebreak every ‘value’ elements.
FormElement.parameter:
- emptyHide: Existence of this item hides an entry with an empty string. This is useful for e.g. Enums, which have an empty entry, but the empty value should not be selectable.
- emptyItemAtStart: Existence of this item inserts an empty entry at the beginning of the selectlist.
- emptyItemAtEnd: Existence of this item inserts an empty entry at the end of the selectlist.
- buttonClass: Instead of the plain radio fields, Bootstrap buttons. are rendered as radio elements. Use one of the following classes: * btn-default (default, grey), * btn-primary (blue), * btn-success (green), * btn-info (light blue), * btn-warning (orange), * btn-danger (red). With a given buttonClass, all buttons (=radios) are rendered horizontal. A value in FormElement.maxlength has no effect.
No preselection:
If there is a default configured on a table column, such a value is selected by default. If the user should actively choose an option, the ‘preselection’ can be omitted by specifying an explicit definition on the FormElement field value:
{{<columnname>:RZ}}
For existing records the shown value is as expected the value of the record. For new records, it’s the value 0, which is typically not one of the ENUM values and therefore nothing is selected.
Type: select¶
- Select lists will be built from one of three sources:
- ‘sql1’: E.g. {{!SELECT type AS label FROM car }} or {{!SELECT type AS label, typeNr AS id FROM car}} or {{!SHOW tables}}.
- Resultset format ‘named’: column ‘label’ and optional a column ‘id’.
- Resultset format ‘index’:
- One column in resultset >> first column represents label
- Two or more columns in resultset >> first column represents id and second column represents label.
- FormElement.parameter:
- itemList = <attribute> - E.g.: itemList=red,blue,orange or itemList=1:red,2:blue:3:orange
- Definition of the enum or set field (only labels, ids are not possible).
- ‘sql1’: E.g. {{!SELECT type AS label FROM car }} or {{!SELECT type AS label, typeNr AS id FROM car}} or {{!SHOW tables}}.
- FormElement.size: <value>
- <value>: <empty>|0|1: Dropdown list.
- <value>: >1: Select field with size rows height. Multiple selection of items is possible.
- FormElement.parameter:
- emptyItemAtStart: Existence of this item inserts an empty entry at the beginning of the selectlist.
- emptyItemAtEnd: Existence of this item inserts an empty entry at the end of the selectlist.
- emptyHide: Existence of this item hides the empty entry. This is useful for e.g. Enums, which have an empty entry and the empty value should not be an option to be selected.
Type: subrecord¶
The FormElement type ‘subrecord’ renders a list of records (so called secondary records), typically to show, edit, delete or add new records. The list is defined as a SQL query. The number of records shown is not limited. These FormElement will be rendered inside the form as a HTML table.
sql1: SQL query to select records. E.g.:
{{!SELECT a.id AS id, CONCAT(a.street, a.streetnumber) AS a, a.city AS b, a.zip AS c FROM Address AS a}}
Notice the exclamation mark after ‘{{‘ - this is necessary to return an array of elements, instead of a single string.
Exactly one column ‘id’ has to exist; it specifies the primary record for the target form. In case the id should not be visible to the user, it has to be named ‘_id’.
Columnname: [title=]<title>[|[width=]<number>][|nostrip][|icon][|link][|url][|mailto][|_rowClass][|_rowTitle]
All parameter are position independet.
Separate parameter by ‘|’.
[title=]<text>: Title of the column. The keyword ‘title=’ is optional. Columns with a title starting with ‘_’ won’t be rendered.
[width=]<number>: Max. width of chars displayed per cell. The keyword ‘width=’ is optional. Default max width: 20. This setting also affects the title of the column.
nostrip: by default, html tags will be stripped off the cell content before rendering. This protects the table layout. ‘nostrip’ deactivates the cleaning to make pure html possible.
icon: the cell value contains the name of an icon in typo3conf/ext/qfq/Resources/Public/icons. Empty cell values will omit an html image tag (=nothing rendered in the cell).
link: value will be rendered as described under Column: _link
url: value will be rendered as a href url.
mailto: value will be rendered as a href mailto.
_rowClass
- The value is a CSS class name(s) which will be rendered in the <tr class=”<_rowClass>”> of the subrecord table.
- The column itself is hidden to the user.
- By using Bootstrap, the following predefined classes are available:
- Text color: text-muted|text-primary|text-success|text-info|text-warning|text-danger (http://getbootstrap.com/css/#helper-classes)
- Row background: active|success|info|warning|danger (http://getbootstrap.com/css/#tables-contextual-classes)
_rowTitle
- Defines the title attribute of a subrecod table row (tooltip).
Examples:
SELECT note1 AS 'Comment', note2 AS 'Comment|50' , note3 AS 'title=Comment|width=100|nostrip', note4 AS '50|Comment', 'checked.png' AS 'Status|icon', email AS 'mailto', CONCAT(homepage, '|Homepage') AS 'url', ELT(status,'info','warning','danger') AS '_rowClass', help AS '_rowTitle' ...
FormElement.parameter
form: Target form, e.g. form=person
page: Target page with detail form. If none specified, use the current page.
title: Title displayed over the table in the current form.
extraDeleteForm: Optional. The per row delete Button will reference the form specified here (for deleting) instead of the default (form).
detail: Mapping of values from the primary form to the target form (defined via form=...).
Syntax:
<source table column name 1|&constant 1>:<target column name 1>[,<source table column name 2|&constant 2>:<target column name 2>][...]
Example: detail=id:personId,&12:xId,&{{a}}:personId
By default, the given value will overwrite values on the target record. In most situations, this is the wished behaviour.
Exceptions of the default behaviour have to be defined on the target form in the corresponding FormElement in the field value by changing the default Store priority definition. E.g. {{<columnname>:RS0}} - For existing records, the store R will provide a value. For new records, store R is empty and store S will be searched for a value: the value defined in detail will be choosen. At last the store ‘0’ is defined as a fallback.
source table column name: E.g. A person form is opened with person.id=5 (r=5). The definition detail=id:personId and form=address maps person.id to address.personId. On the target record, the column personId becomes ‘5’.
Constant ‘&’: Indicate a ‘constant’ value. E.g. &12:xId or {{...}} (all possibilities, incl. further SELECT statements) might be used.
Type: time¶
- Range time: ‘00:00:00’ to ‘23:59:59’ or ‘00:00:00’. (http://dev.mysql.com/doc/refman/5.5/en/datetime.html)
- Optional:
- FormElement.parameter * showSeconds: 0|1 - shows the seconds. Independent if the user specifies seconds, they are displayed ‘1’ or not ‘0’. * showZero: 0|1 - For an empty timestamp, With ‘0’ nothing is displayed. With ‘1’ the string ‘00:00[:00]’ is displayed.
Type: upload¶
An upload element is based on a ‘file browse’-button and a ‘trash’-button (=delete). Only one of them is shown at a time. The ‘file browse’-button is displayed, if there is no file uploaded already. The ‘trash’-button is displayed, if there is a file uploaded already.
After clicking on the browse brutton , the user can select a file from the local filesystem. After choosing the file, the upload starts immediately, shown by a turning wheel. When the server received the whole file and accepts the file, the ‘file browse’-button dissappears and the filename is shown, followed by a ‘trash’-button. Either the user is satisfied now or the user can delete the uploaded file (and maybe upload another one).
Until this point, the file is cached on the server but not copied to the fileDestination. The user have to save the current record, either to finalize the upload or to delete a previous uploaded file.
The FormElement behaves like a ‘native FormElement’ (showing controls/text on the form) as well as an ‘action FormElement’ by fireing queries and doing some additional actions during form save. Inside the Form editor it’s shown as a ‘native FormElement’.
FormElement.parameter:
accept: image/*,video/*,audio/*,.doc,.docx,.pdf,<mime type>
fileDestination: Destination where to copy the file. A good practice is to specify a relative fileDestination - such an installation (filesystem and database) are moveable.
If the original filename should be part of fileDestination, the variable {{filename}} (STORE_VARS) can be used. Example
fileDestination={{SELECT 'fileadmin/user/pictures/', p.name, '-{{filename}}' FROM Person AS p WHERE p.id={{id:R0}} }}
- The original filename will be sanatized: only alnum characters are allowed. German ‘umlaut’ will be replaced by ‘ae’, ‘ue’, ‘oe’. All non valid characters will be replaced by ‘-‘.
If a file already exist under fileDestination, an error message is shown and ‘save’ is aborted. The user has no possibility to overwrite the already existing file. If the whole workflow is correct, this situation should no arise. Check also fileReplace below.
All necessary subdirectories in fileDestination are automatically created.
Using the current record id in the fileDestination: Using {{r}} is problematic for a ‘new’ primary record: that one is still ‘0’ at the time of saving. Use {{id:R0}} instead.
slaveId, sqlBefore, sqlInsert, sqlUpdate, sqlDelete, sqlUpdate, sqlAfter: Only used in Upload advanced mode.
fileReplace=always: If fileDestination exist - replace it by the new one.
Deleting a record and the referenced file¶
If the user deletes a record (e.g. pressing the delete button on a form) which contains reference(s) to files, such files are deleted too. Slave records, which might be also deleted through a ‘delete’-form, are not checked for file references and therefore such files are not deleted on the filesystem.
Only columns where the columname contains pathFileName are checked for file references. Therefore, always choose a columnanme which contains pathFileName.
If there are other records, which references the same file, such files are not deleted. It’s a very basic check: just the current column of the current table is compared. In general it’s not a good idea to have mutliple references to a single file. Therefore this check is just a fallback.
Upload simple mode¶
Requires: ‘upload’-FormElement.name = ‘column name’ of an column in the primary table.
After moving the file to fileDestination, the current record/column will be updated to fileDestination. The database definition of the named column has to be a string variant (varchar, text but not numeric or else). On form load, the column value will be displayed as path/filename. Deleting an uploaded file in the form (by clicking on the trash near beside) will delete the file on the filesystem as well. The column will be updated to an empty string.
This happens automatically without any further definiton in the ‘upload’-FormElement.
Multiple ‘upload’-FormElements per form are possible. Each of it needs an own table column.
Upload advanced mode¶
Requires: ‘upload’-FormElement.name is unknown as a column in the primary table.
This mode will serve further database structure scenarios.
A typical name for such an ‘upload’-FormElement, to show that the name does not exist in the table, might start with ‘my’, e.g. ‘myUpload1’.
FormElement.value: The path/filename, shown during ‘form load’ to indicate a previous uploaded file, has to be queried with this field. E.g.:
{{SELECT pathFilenamePicture FROM Note WHERE id={{slaveId}} }}
FormElement.parameter:
fileDestination: determine the path/filename. E.g.:
fileDestination=fileadmin/person/{{name:R0}}_{{id:R}}/uploads/picture_{{filename}}
slaveId: Defines the target record where to retrieve and store the path/filename of the uploaded file. Check also slaveId. E.g.:
slaveId={{SELECT id FROM Note WHERE pId={{id:R0}} AND type='picture' LIMIT 1}}
sqlBefore: fired during a form save, before the following queries are fired.
sqlInsert: fired if slaveId=0 and an upload exist (user has choosen a file):
sqlInsert={{INSERT INTO Note (pId, type, pathFileName) VALUE ({{id:R0}}, 'image', '{{fileDestination}}') }}
sqlUpdate: fired if slaveId>0 and an upload exist (user has choosen a file). E.g.:
sqlUpdate={{UPDATE Note SET pathFileName = '{{fileDestination}}' WHERE id={{slaveId}} LIMIT 1}}
sqlDelete: fired if slaveId>0 and no upload exist (user has not choosen a file). E.g.:
sqlDelete={{DELETE FROM Note WHERE id={{slaveId:V}} LIMIT 1}}
sqlAfter: fired after all previous queries have been fired. Might update the new created id to a primary record. E.g.:
sqlUpdate={{UPDATE Person SET noteIdPicture = {{slaveId}} WHERE id={{id:R0}} LIMIT 1 }}
Class: Action¶
Type: before... | after...¶
These type of ‘action’ FormElements will be used to implement data validation or creating/updating additional records.
Types:
- beforeLoad
- good to grant access permission.
- afterLoad
- beforeSave
- good to prohibit creating of duplicate records.
- afterSave
- good to create & update additional records.
- beforeInsert
- afterInsert
- beforeUpdate
- afterUpdate
- beforeDelete
- afterDelete
sqlValidate¶
Perform checks by fireing a SQL query and expecting a predefined number of selected records.
- OK: the expectRecords number of records has been selected. Continue processing the next FormElement.
- Fail: the expectRecords number of records has not been selected (less or more): Display the error message messageFail and abort the whole (!) current form load or save.
FormElement.parameter:
- requiredList - List of native-FormElement names: only if all of those elements are filled (!=0 and !=’‘), the current action-FormElement will be processed. This will enable or disable the check, based on the user input! If no native-FormElement names are given, the specified check will always be performed.
- sqlValidate - validation query. E.g.: sqlValidate={{!SELECT id FROM Person AS p WHERE p.name LIKE {{name:F:all}} AND p.firstname LIKE {{firstname:F:all}} }}
- Pay attention to {{!... after the equal sign.
- expectRecords - number of expected records.
- expectRecords = 0 or expectRecords = 0,1 or expectRecords = {{SELECT COUNT(id) FROM Person}}
- Separate multiple valid record numbers by ‘,’. If at least one of those matches, the check will pass successfully.
- messageFail - Message to show. E.g.: messageFail = There is already a person called {{firstname:F:all}} {{name:F:all}}
slaveId¶
FormElement.parameter:
- slaveId:
- Auto fill: name the action action-FormElement equal to an existing column (table from the current form definition). slaveId will be automatically filled with the value of the named column.
- If there is no such named columnname, set slaveId = 0.
- Explicit definition: slaveId = 123 or slaveId = {{SELECT id ...}}
Note:
- {{slaveId}} can be used in any query of the current FormElement.
- If the action-FormElement name exist as a column in the master record: Update that column automatically with the recent slaveId
- After an INSERT the last_insert_id() becomes the slaveId).
sqlBefore / sqlInsert / sqlUpdate / sqlDelete / sqlAfter¶
- Save values of a form to different record(s), optionally on different table(s).
- Typically useful on ‘afterSave’ - be careful when using it earlier, e.g. beforeLoad.
FormElement.parameter:
- requiredList - List of native-FormElement: only if all of those elements are filled, the current action-FormElement will be processed.
- sqlBefore: always fired (before any sqlInsert or sqlUpdate)
- sqlInsert: fired if slaveId = 0 or slaveId = ‘’.
- sqlUpdate: fired if slaveId > 0:
- sqlDelete: always fired (after sqlInsert or sqlUpdate) - the definition, when this query is fired, might change in the future.
- sqlAfter: always fired (after sqlInsert, sqlUpdate or sqlDelete).
Example¶
Situation 1: master.xId=slave.id (1:1)
Name the action element ‘xId’: than {{slaveId}} will be automatically set to the value of ‘master.xId’
- {{slaveId}} == 0 ? ‘sqlInsert’ will be fired.
- {{slaveId}} != 0 ? ‘sqlUpdate’ will be fired.
- In case of fireing ‘sqlInsert’, the ‘slave.id’ of the new created record are copied to master.xId (the database will
be updated automatically).
- If the automatic update of the master record is not suitable, the action element should have no name or a name
which does not exist as a column of the master record. Define slaveId={{SELECT id ...}}
Situation 2: master.id=slave.xId (1:n)
- Name the action element different to any columnname of the master record (or no name).
- Determine the slaveId: slaveId={{SELECT id FROM slave WHERE slave.xxx={{...}} LIMIT 1}}
- {{slaveId}} == 0 ? ‘sqlInsert’ will be fired.
- {{slaveId}} != 0 ? ‘sqlUpdate’ will be fired.
Type: sendmail¶
Send mail(s) will be processed after:
- saving the record ,
- processing all uploads,
- processing afterSave action FormElements.
FormElement.value: Body of the email.
FormElement.parameter:
- sendMailTo - Comma-separated list of receiver email addresses. Optional: ‘realname <john@doe.com>. If there is no recipient email address, no mail will be sent.
- sendMailCc - Comma-separated list of receiver email addresses. Optional: ‘realname <john@doe.com>.
- sendMailBcc - Comma-separated list of receiver email addresses. Optional: ‘realname <john@doe.com>.
- sendMailFrom - Sender of the email. Optional: ‘realname <john@doe.com>’. Mandatory.
- sendMailSubject - Subject of the email.
- sendMailReplyTo - Reply this email address. Optional: ‘realname <john@doe.com>’.
- sendMailFlagAutoSubmit - on|off - If ‘on’ (default), the mail contains the header ‘Auto-Submitted: auto-send’ - this suppress a) OoO replies, b) forwarding of emails.
- sendMailGrId - Will be copied to the mailLog record. Helps to setup specific logfile queries.
- sendMailXId - Will be copied to the mailLog record. Helps to setup specific logfile queries.
To use values of the submitted form, use the STORE_FORM. E.g. {{name:F:allbut}}
To use the id of a new created or already existing one, use the STORE_RECORD. E.g. {{id:R}}
Dynamic Update¶
The ‘Dynamic Update’ feature makes a form more interactive. If a user change a FormElement who is tagged with ‘dynamicUpdate’, all elements who are tagged with ‘DynamicUpdate’, will be recalculated and rerendered.
The following fields will be recalculated during ‘Dynamic Update’
- ‘modeSql’ - Possible values: ‘show’, ‘required’, ‘readonly’, ‘hidden’
- ‘value’
- ‘parameter.*’ - especially ‘itemList’
- ‘note’
- ‘label’
To make a form dynamic:
Mark all FormElements with dynamic update`=`enabled, which initiates or receives updates.
Define the receiving FormElements in a way, that they will interpret the recent user change. The form variable of the specific sender FormElement {{<sender element>:F:<sanitize>}} should be part of one of the above fields to get an impact. E.g.:
[receiving *FormElement*].parameter: itemList={{ SELECT IF({{carPriceRange:FE:alnumx}}='expensive','Ferrari,Tesla,Jaguar','General Motors,Honda,Seat,Fiat') }}
Examples¶
- Master FormElement ‘music’ is a radio/enum of ‘classic’, ‘jazz’, ‘pop’.
Content of a select list¶
- Slave FormElement ‘interpret’ is ‘select’-list, depending of ‘music’
sql={{!SELECT name FROM interpret WHERE music={{music:FE:alnumx}} ORDER BY name}}
Show / Hide a FormElement¶
- Slave ‘interpret’ is displayed only for ‘pop’:
modeSql={{SELECT IF( '{{music:FR:alnumx}}'='pop' ,'show', 'hidden' }}
Form Layout¶
The forms will be rendered with Bootstrap CSS classes, based on the 12 column grid model (Bootstrap 3.x). Generally a 3 column layout for label columns on the left side, an input field column in the middle and a note column on the right side will be rendered.
The used default column (=bootstrap grid) width is 3,6,3 for label, input, note.
- The system wide default can be changed via config.qfq.ini config.qfq.ini - the new settings are the default settings for all forms.
- Per Form settings can be done in the Form parameter field. They overwrite the system wide default.
- Per FormElement settings can be done in the FormElement parameter field. They overwrite the Form setting.
A column will be switched off (no wrapping via <div class=’col-md-?>) by setting a 0 on the respective column.
Custom field width¶
Per FormElement set BS Label Columns, BS Input Columns or BS Note Columns to customize an individual width. The sum of these three columns should always be 12.
Multiple Elements per row¶
Every row is by default wrapped in a <div class=’form-group’> and every column is wrapped in a <div class=’col-md-?>. To display multiple input elements in one row, the wrapping of the FormElement row and of the three columns can be customized via the checkboxes of Label / Input / Note. Every open and every close tag can be individually switched on or off.
E.g. to display 2 FormElements in a row with one label (first FormElement) and one note (last FormElement) we need the following (switch off all non named):
- First FormElement
- open row tag: row ,
- open and close label tag: label, /label,
- open and close field tag: input, /input,
- Second FormElement
- open and close field tag: input, /input,
- open and close note tag: note, /note,
- close row tag: /row ,
Best practice¶
Central configured values¶
Any variable in config.qfq.ini can be used by {{<varname>:Y}} in form or report statements.
E.g.
TECHNICAL_CONTACT = jane.doe@example.net
Could be used in an FormElement.type = sendmail with parameter setting sendMailFrom={{TECHNICAL_CONTACT:Y}}.
Debug Report¶
Writing “report’s” in the nested notation or long queries broken over several lines, might not interpreted as wished. Best for debugging is to specify in the tt-content record:
debugShowBodyText = 1
- Note: Debug information is only display if it’s enabled in config.ini by
- SHOW_DEBUG_INFO=yes or
- SHOW_DEBUG_INFO=auto and logged in in the same Browser as a Typo3 backend user.
More detailed error messages¶
If SHOW_DEBUG_INFO is enabled, a full stacktrace and variable contents are displayed in case of an error.
Person search form¶
QFQ content record:
# Creates a small form that redirects back to this page
10 {
sql = SELECT '_'
head = <form action='#' method='get'><input type='hidden' name='id' value='{{pageId:T}}'>Search: <input type='text' name='search' value='{{search:CE:all}}'><input type='submit' value='Submit'></form>
}
# SQL statement will find and list all the relevant forms
20 {
sql = SELECT CONCAT('?detail&form=form&r=', f.id) AS _Pagee, f.id, f.name, f.title
FROM Form AS f
WHERE f.name LIKE '%{{search:CE:all}}%'
head = <table class='table'>
tail = </table>
rbeg = <tr>
rend = </tr>
fbeg = <td>
fend = </td>
}
Form: compute next free ‘ord’ automatically¶
Requirement: new records should automatically get the highest number plus 10 for their ‘ord’ value. Existing records should not be altered.
Version 1¶
Compute the next ‘ord’ in advance in the subrecord field of the primary form. Submit that value to the new record via SIP parameter to the secondary form.
On the secondary form: for ‘new’ records choose the computed value, for existing records leave the value unchanged.
Primary form, subrecord FormElement, field parameter: set
detail=id:formId,{{SELECT '&', IFNULL(fe.ord,0)+10 FROM Form AS f LEFT JOIN *FormElement* AS fe ON fe.formId=f.id WHERE f.id={{r:S0}} ORDER BY fe.ord DESC LIMIT 1}}:ord
Secondary form, ord FormElement, field value: set
`{{RS0}}`.
Version 2¶
Compute the next ‘ord’ as default value direct inside the secondary form. No change is needed for the primary form.
- Secondary form, ord FormElement, field value: set {{SELECT IF({{ord:R0}}=0, MAX(IFNULL(fe.ord,0))+10,{{ord:R0}}) FROM (SELECT 1) AS a LEFT JOIN FormElement AS fe ON fe.formId={{formId:S0}} GROUP BY fe.formId}}.
Form: Person Wizard - firstname, city¶
Requirement: A form that displays the column ‘firstname’ from table ‘Person’ and ‘city’ from table ‘Address’. If the records not exist, the form should create it.
Form primary table: Person
Form slave table: Address
Relation: Person.id = Address.personId
- Form: wizard
- Name: wizard
- Title: Person Wizard
- Table: Person
- Render: bootstrap
- FormElement: firstname
- Class: native
- Type: text
- Name: firstname
- Label: Firstname
- FormElement: email, text, 20
- Class: native
- Type: text
- Name: city
- Label: City
- Value: {{SELECT city FROM Address WHERE personId={{r}} ORDER BY id LIMIT 1}}
- FormElement: insert/update address record
- Class: action
- Type: afterSave
- Label: Manage Address
- Parameter:
- slaveId={{SELECT id FROM Address WHERE personId={{r}} ORDER BY id LIMIT 1}}
- sqlInsert={{INSERT INTO Address (personId, city) VALUES ({{r}}, ‘{{city:F:allbut:s}}’) }}
- sqlUpdate={{UPDATE Address SET city=’{{city:F:allbut:s}}’ WHERE id={{slaveId:V}} }}
- sqlDelete={{DELETE FROM Address WHERE id={{slaveId:V}} AND ‘’=’{{city:F:allbut:s}}’ LIMIT 1}}
Form: Person Wizard - firstname, single note¶
Requirement: A form that displays the column ‘firstname’ from table ‘Person’ and ‘note’ from table ‘Note’. If the records don’t exist, the form should create it. Column Person.noteId points to Note.id
Form primary table: Person
Form slave table: Address
Relation: Person.id = Address.personId
- Form: wizard
- Name: wizard
- Title: Person Wizard
- Table: Person
- Render: bootstrap
- FormElement: firstname
- Class: native
- Type: text
- Name: firstname
- Label: Firstname
- FormElement: email, text, 20
- Class: native
- Type: text
- Name: note
- Label: Note
- Value: {{SELECT Note FROM Note AS n, Person AS p WHERE p.id={{r}} AND p.noteId=n.id ORDER BY id }}
- FormElement: insert/update address record
- Class: action
- Type: afterSave
- Name: noteId
- Label: Manage Note
- Parameter:
- sqlInsert={{INSERT INTO Note (note) VALUES (‘{{note:F:allbut:s}}’) }}
- sqlUpdate={{UPDATE Note SET note=’{{note:F:allbut:s}}’ WHERE id={{slaveId:V}} }}
Icons Template Group¶
- FormElement.parameter
tgAddClass=btn alert-success
tgAddText=<span class="glyphicon glyphicon-plus" aria-hidden="true"></span>
tgRemoveClass=btn btn-danger alert-danger
tgRemoveText=<span class="glyphicon glyphicon-remove" aria-hidden="true"></span>
Chart¶
- QFQ delivers a chart JavaScript lib: https://github.com/nnnick/Chart.js.git. Docs: http://www.chartjs.org/docs/
- The library is not sourced in the HTML page automatically. To do it, either include the lib
typo3conf/ext/qfq/Resources/Public/JavaScript/Chart.min.js:
- in the specific tt_content record (shown below in the example) or
- system wide via Typo3 Template record.
- By splitting HTML and JavaScript code over several lines, take care not accidently to create a ‘nesting’-end token.
Check the line after 10.tail =. It’s ‘}’ alone on one line. This is a valid ‘nesting’-end token!. There are two options
to circumvent this:
- Don’t nest the HTML & JavaScript code - bad workaround, this is not human readable.
- Select different nesting token, e.g. ‘<’ / ‘>’ (check the first line on the following example).
# <
10.sql = SELECT '_'
10.head =
<div style="height: 1024px; width: 640px;">
<h3>Distribution of FormElement types over all forms</h3>
<canvas id="barchart" width="1240" height="640"></canvas>
</div>
<script src="typo3conf/ext/qfq/Resources/Public/JavaScript/Chart.min.js"></script>
<script>
$(function () {
var ctx = document.getElementById("barchart");
var barChart = new Chart(ctx, {
type: 'bar',
data: {
10.tail =
}
});
});
</script>
# Labels
10.10 <
sql = SELECT "'", fe.type, "'" FROM FormElement AS fe GROUP BY fe.type ORDER BY fe.type
head = labels: [
tail = ],
rsep = ,
>
# Data
10.20 <
sql = SELECT COUNT(fe.id) FROM FormElement AS fe GROUP BY fe.type ORDER BY fe.type
head = datasets: [ { data: [
tail = ], backgroundColor: "steelblue", label: "FormElements" } ]
rsep = ,
>
Upload Form Simple¶
Table Person
Name | Type |
---|---|
id | int |
name | varchar(255) |
pathFileNamePicture | varchar(255) |
pathFileNameAvatar | varchar(255) |
Form:
- Name: UploadSimple
- Table: Person
FormElements:
Name: name
- Type: text
- Label: Name
Name: pathFileNamePicture
Type: upload
Label: Picture
Parameter:
fileDestination=fileadmin/user/{{id:R0}}-picture-{{filename}}
Name: pathFileNameAvatar
Type: upload
Label: Avatar
Parameter:
fileDestination=fileadmin/user/{{id:R0}}-avatar-{{filename}}
Upload Form Advanced 1¶
Table: Person
Name Type id int name varchar(255)
Table: Note
Name Type id int pId int type varchar(255) pathFileName varchar(255)
Form:
- Name: UploadAdvanced1
- Table: Person
FormElements
Name: name
- Type: text
- Label: Name
Name: mypathFileNamePicture
Type: upload
Label: Picture
Value: {{SELECT pathFileName FROM Note WHERE id={{slaveId}} }}
Parameter:
fileDestination=fileadmin/user/{{id:R0}}-picture-{{filename}} slaveId={{SELECT id FROM Note WHERE pId={{id:R0}} AND type='picture' LIMIT 1}} sqlInsert={{INSERT INTO Note (pathFileName, type, pId) VALUE ('{{fileDestination}}', 'picture', {{id:R0}}) }} sqlUpdate={{UPDATE Note SET pathFileName = '{{fileDestination}}' WHERE id={{slaveId}} LIMIT 1}} sqlDelete={{DELETE FROM Note WHERE id={{slaveId}} LIMIT 1}}
Name: mypathFileNameAvatar
Type: upload
Label: Avatar
Value: {{SELECT pathFileName FROM Note WHERE id={{slaveId}} }}
Parameter:
fileDestination=fileadmin/user/{{id:R0}}-avatar-{{filename}} slaveId={{SELECT id FROM Note WHERE pId={{id:R0}} AND type='avatar' LIMIT 1}} sqlInsert={{INSERT INTO Note (pathFileName, type, pId) VALUE ('{{fileDestination}}', 'avatar', {{id:R0}}) }} sqlUpdate={{UPDATE Note SET pathFileName = '{{fileDestination}}' WHERE id={{slaveId}} LIMIT 1}} sqlDelete={{DELETE FROM Note WHERE id={{slaveId}} LIMIT 1}}
Upload Form Advanced 2¶
Table: Person
Name Type id int name varchar(255) noteIdPicture int noteIdAvatar int
Table: Note
Name Type id int pathFileName varchar(255)
Form:
- Name: UploadAdvanced2
- Table: Person
FormElements
Name: name
- Type: text
- Label: Name
Name: mypathFileNamePicture
Type: upload
Label: Picture
Value: {{SELECT pathFileName FROM Note WHERE id={{slaveId}} }}
Parameter:
fileDestination=fileadmin/user/{{id:R0}}-picture-{{filename}} slaveId={{SELECT id FROM Note WHERE id={{noteIdPicture}} LIMIT 1}} sqlInsert={{INSERT INTO Note (pathFileName) VALUE ('{{fileDestination}}') }} sqlUpdate={{UPDATE Note SET pathFileName = '{{fileDestination}}' WHERE id={{slaveId}} LIMIT 1}} sqlDelete={{DELETE FROM Note WHERE id={{slaveId}} LIMIT 1}} sqlAfter={{UPDATE Person SET noteIdPicture={{slaveId}} WHERE id={{id:R0}} LIMIT 1
Name: mypathFileNameAvatar
Type: upload
Label: Avatar
Value: {{SELECT pathFileName FROM Note WHERE id={{slaveId}} }}
Parameter:
fileDestination=fileadmin/user/{{id:R0}}-avatar-{{filename}} slaveId={{SELECT id FROM Note WHERE id={{noteIdAvatar}} LIMIT 1}} sqlInsert={{INSERT INTO Note (pathFileName) VALUE ('{{fileDestination}}') }} sqlUpdate={{UPDATE Note SET pathFileName = '{{fileDestination}}' WHERE id={{slaveId}} LIMIT 1}} sqlDelete={{DELETE FROM Note WHERE id={{slaveId}} LIMIT 1}} sqlAfter={{UPDATE Person SET noteIdAvatar={{slaveId}} WHERE id={{id:R0}} LIMIT 1
FAQ¶
- Q: A variable {{<var>}} is shown as empty string, but there should be a value.
- A: The sanatize rule is violeted and therefore the value has been removed. Set {{<var>:<store>:all}} as a test. Only STORE_CLIENT and STORE_FORM will be sanatized.