[BUGFIX] Fix typo in form documentation
[Packages/TYPO3.CMS.git] / typo3 / sysext / form / Documentation / Concepts / FormEditor / Index.rst
1 .. include:: ../../Includes.txt
2
3
4 .. _concepts-formeditor:
5
6 Form editor
7 ===========
8
9
10 .. _concepts-formeditor-general:
11
12 What does it do?
13 ----------------
14
15 The ``form editor`` is a powerful graphical user interface which allows the
16 backend editor to create ``form definitions`` without writing a single line
17 of code. Those ``form definitions`` will be used by the frontend process to
18 render beautiful forms.
19
20 The ``form editor`` is a modular interface which consists of several
21 components:
22
23 - Stage: central visual component of the ``form editor`` which displays the
24 form elements in an abstract view and a frontend preview
25 - Tree: displays the structure of the form as a tree
26 - Inspector: context specific toolbar which handles the visual display of
27 form element options and allows editing those
28 - Core: includes core functionalities of the ``form editor``
29 - ViewModel: defines and steers the visual display
30 - Mediator: delegates events of the components
31 - Modals: processes modals
32 - FormEditor: provides API functions
33 - Helper: helper functions which mainly allow the manipulation of DOM
34 elements
35
36 Generally speaking, the ``Modals``, ``Inspector``, and ``Stage`` components
37 can be adapted through configuration. Especially the ``Inspector`` component
38 is modular and extremely flexible. As an integrator, you can reuse so-called
39 ``inspector editors``. Those elements are input fields of different types
40 which allow the backend editor to alter all of the available form element
41 options.
42
43 .. figure:: ../../Images/javascript_module_interaction.png
44 :alt: JavaScript module interaction
45
46 JavaScript module interaction
47
48 There is a general ``form editor`` configuration which can be found below
49 the following configuration path:
50
51 .. code-block:: yaml
52
53 TYPO3:
54 CMS:
55 Form:
56 prototypes:
57 standard:
58 formEditor:
59
60 Furthermore, you are able to configure the ``form editor`` regarding its
61 different aspects. The configuration can be found below the following
62 configuration paths:
63
64 .. code-block:: yaml
65
66 TYPO3:
67 CMS:
68 Form:
69 prototypes:
70 standard:
71 formElementsDefinition:
72 <formElementTypeIdentifier>:
73 formEditor:
74 finishersDefinition:
75 <finisherIdentifier>
76 formEditor:
77 validatorsDefinition:
78 <validatorIdentifier>
79 formEditor:
80
81
82 .. _concepts-formeditor-stage:
83
84 Stage
85 -----
86
87 The ``Stage`` is the central visual component of the form editor which
88 displays the form elements in two different modes:
89
90 - abstract view: all form elements of a ``Page`` are presented in an
91 abstract way,
92 - frontend preview: renders the form like it will (nearly) be displayed in
93 the frontend ('nearly' since you have to make sure that your frontend CSS
94 is also loaded in the backend in order to get the exact preview).
95
96 Per default, the frontend templates of EXT:form are based on Twitter
97 Bootstrap. Since the backend of TYPO3 CMS also depends on this CSS framework,
98 the corresponding CSS files are already loaded in the backend context.
99 Nevertheless, certain parts of the CSS were overridden and extended in order
100 to meet the specific needs of the TYPO3 backend. Thus, the frontend preview
101 in the backend could differ compared to the "real" frontend.
102
103 If your frontend preview requires loading additional CSS or a CSS framework
104 then go ahead and configure a specific ``prototype`` accordingly.
105
106 Beside the frontend templates, there are also templates for the abstract
107 view, i.e. you can customize the rendering of the abstract view for each
108 form element. If you have created your own form elements, in most cases you
109 will fall back to the already existing Fluid templates. But remember, you
110 are always able to create you own Fluid templated and adapt the abstract view
111 till it suits your needs.
112
113 For more information, read the following chapter: ':ref:`Common abstract view form element templates<apireference-formeditor-stage-commonabstractformelementtemplates>`'.
114
115
116 .. _concepts-formeditor-inspector:
117
118 Inspector
119 ---------
120
121 The ``Inspector`` component is situated on the right side of the ``form
122 editor``. It is a modular, extremely flexible, and context specific toolbar
123 which depends on the chosen form element. The ``Inspector`` allows editing
124 the form element's options with the help of so-called ``inspector editors``.
125 For the most parts, the interface can be easily customized by writing
126 YAML configuration. For each form element you can define which properties
127 are available and in which way they can be edited.
128
129 In addition to the editable form element properties (like ``properties.placeholder``)
130 there are so-called ``property collections`` which can be written by the
131 ``form editor`` as well. Their definition is stored on the hierarchical
132 level of a form element. Right now, there are the following ``property
133 collections``:
134
135 - validators
136 - finishers
137
138 ``Property collections`` also make use of ``inspector editors`` in order to
139 configure them properly. Due to this, we can do a lot of cool stuff. Imagine
140 we have got a validator "Number range" with two validator options called
141 "Minimum" and "Maximum". Additionally, we have got two form elements "Age
142 spouse" and "Age infant". For both form elements the validator is available
143 but for the form element "Age child" the validator option "Minimum" is not
144 editable and the option "Maximum" is pre-filled with a certain value.
145
146
147 .. _concepts-formeditor-basicjavascriptconcepts:
148
149 Basic JavaScript concepts
150 -------------------------
151
152 The form framework was designed to be as extendible as possible. Sooner or
153 later, you want to customize the components of the ``form editor`` using
154 JavaScript. This is especially true if you want to create your own
155 ``inspector editors``. In order to achieve this, you can implement your own
156 JavaScript modules. Those modules will include the required algorithms for
157 the ``inspector editors`` and the ``abstract view`` as well as your own
158 event listing.
159
160
161 .. _concepts-formeditor-basicjavascriptconcepts-registercustomjavascriptmodules:
162
163 Register custom JavaScript modules
164 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
165
166 The following YAML configuration registers an additional JavaScript module.
167
168 .. code-block:: yaml
169
170 TYPO3:
171 CMS:
172 Form:
173 prototypes:
174 standard:
175 formEditor:
176 dynamicRequireJsModules:
177 additionalViewModelModules:
178 - 'TYPO3/CMS/MySitePackage/Backend/FormEditor/ViewModel'
179
180 According to the example shown above, the JavaScript files have to be stored
181 within the folder ``my_site_package/Resources/Public/JavaScript/Backend/FormEditor/ViewModel.js``.
182 In the TYPO3 backend JavaScript files are loaded via RequireJS which depends
183 on a certain convention. The name of the module starts with **TYPO3/CMS**/MySitePackage/Backend/FormEditor/ViewModel
184 followed by your extension key TYPO3/CMS/**MySitePackage**/Backend/FormEditor/ViewModel.
185 Thus, you have to ensure that the module is stored within a subfolder of ``my_site_package/Resources/Public/JavaScript/``.
186 The part TYPO3/CMS/MySitePackage/**Backend/FormEditor**/ViewModel tells you
187 that your files have to be stored in my_site_package/Resources/Public/JavaScript/**Backend/FormEditor**/.
188 The last section TYPO3/CMS/MySitePackage/Backend/FormEditor/**ViewModel**
189 states the name of the JavaScript file without the file extension (.js).
190
191 Check out the following base template which shows you the recommended way
192 for setting up your own module.
193
194 .. code-block:: javascript
195
196 /**
197 * Module: TYPO3/CMS/MySitePackage/Backend/FormEditor/ViewModel
198 */
199 define(['jquery',
200 'TYPO3/CMS/Form/Backend/FormEditor/Helper'
201 ], function($, Helper) {
202 'use strict';
203
204 return (function($, Helper) {
205
206 /**
207 * @private
208 *
209 * @var object
210 */
211 var _formEditorApp = null;
212
213 /**
214 * @private
215 *
216 * @return object
217 */
218 function getFormEditorApp() {
219 return _formEditorApp;
220 };
221
222 /**
223 * @private
224 *
225 * @return object
226 */
227 function getPublisherSubscriber() {
228 return getFormEditorApp().getPublisherSubscriber();
229 };
230
231 /**
232 * @private
233 *
234 * @return object
235 */
236 function getUtility() {
237 return getFormEditorApp().getUtility();
238 };
239
240 /**
241 * @private
242 *
243 * @param object
244 * @return object
245 */
246 function getHelper() {
247 return Helper;
248 };
249
250 /**
251 * @private
252 *
253 * @return object
254 */
255 function getCurrentlySelectedFormElement() {
256 return getFormEditorApp().getCurrentlySelectedFormElement();
257 };
258
259 /**
260 * @private
261 *
262 * @param mixed test
263 * @param string message
264 * @param int messageCode
265 * @return void
266 */
267 function assert(test, message, messageCode) {
268 return getFormEditorApp().assert(test, message, messageCode);
269 };
270
271 /**
272 * @private
273 *
274 * @return void
275 * @throws 1491643380
276 */
277 function _helperSetup() {
278 assert('function' === $.type(Helper.bootstrap),
279 'The view model helper does not implement the method "bootstrap"',
280 1491643380
281 );
282 Helper.bootstrap(getFormEditorApp());
283 };
284
285 /**
286 * @private
287 *
288 * @return void
289 */
290 function _subscribeEvents() {
291 getPublisherSubscriber().subscribe('some/eventName/you/want/to/handle', function(topic, args) {
292 myCustomCode();
293 });
294 };
295
296 /**
297 * @private
298 *
299 * @return void
300 */
301 function myCustomCode() {
302 };
303
304 /**
305 * @public
306 *
307 * @param object formEditorApp
308 * @return void
309 */
310 function bootstrap(formEditorApp) {
311 _formEditorApp = formEditorApp;
312 _helperSetup();
313 _subscribeEvents();
314 };
315
316 /**
317 * Publish the public methods.
318 * Implements the "Revealing Module Pattern".
319 */
320 return {
321 bootstrap: bootstrap
322 };
323 })($, Helper);
324 });
325
326
327 .. _concepts-formeditor-basicjavascriptconcepts-events:
328
329 Events
330 ^^^^^^
331
332 The event handling of EXT:form is based on the ``Publish/Subscribe Pattern``.
333 To learn more about this terrific pattern, check out this website: https://addyosmani.com/resources/essentialjsdesignpatterns/book/.
334 Please not that the processing sequence of the subscribers cannot be
335 influenced. Furthermore, there is no information flow between the
336 subscribers. All events have to be arranged asynchronously.
337
338 For more information, head to the API reference and read the section about
339 ':ref:`Events<concepts-formeditor-basicjavascriptconcepts-events>`'.
340
341
342 .. _concepts-formeditor-basicjavascriptconcepts-formelementmodel:
343
344 FormElement model
345 ^^^^^^^^^^^^^^^^^
346
347 Within the JavaScript code, each form element is represented by a
348 `FormElement model``. This model can be seen as a copy of the ``form
349 definition'' enriched by some additional data. The following example shows
350 you a ``form definition`` and the debug output of the corresponding
351 ``FormElement model``.
352
353 .. code-block:: yaml
354
355 identifier: javascript-form-element-model
356 label: 'JavaScript FormElement model'
357 type: Form
358 finishers:
359 -
360 identifier: EmailToReceiver
361 options:
362 subject: 'Your message: {subject}'
363 recipientAddress: your.company@example.com
364 recipientName: 'Your Company name'
365 senderAddress: '{email}'
366 senderName: '{name}'
367 replyToAddress: ''
368 carbonCopyAddress: ''
369 blindCarbonCopyAddress: ''
370 format: html
371 attachUploads: 'true'
372 translation:
373 language: ''
374 renderables:
375 -
376 identifier: page-1
377 label: 'Contact Form'
378 type: Page
379 renderables:
380 -
381 identifier: name
382 label: Name
383 type: Text
384 properties:
385 fluidAdditionalAttributes:
386 placeholder: Name
387 defaultValue: ''
388 validators:
389 -
390 identifier: NotEmpty
391
392 .. code-block:: javascript
393
394 {
395 "identifier": "javascript-form-element-model",
396 "label": "JavaScript FormElement model",
397 "type": "Form",
398 "prototypeName": "standard",
399 "__parentRenderable": null,
400 "__identifierPath": "example-form",
401 "finishers": [
402 {
403 "identifier": "EmailToReceiver",
404 "options": {
405 "subject": "Your message: {subject}",
406 "recipientAddress": "your.company@example.com",
407 "recipientName": "Your Company name",
408 "senderAddress": "{email}",
409 "senderName": "{name}",
410 "replyToAddress": "",
411 "carbonCopyAddress": "",
412 "blindCarbonCopyAddress": "",
413 "format": "html",
414 "attachUploads": true,
415 "translation": {
416 "language": ""
417 }
418 }
419 }
420 ],
421 "renderables": [
422 {
423 "identifier": "page-1",
424 "label": "Contact Form",
425 "type": "Page",
426 "__parentRenderable": "example-form (filtered)",
427 "__identifierPath": "example-form/page-1",
428 "renderables": [
429 {
430 "identifier": "name",
431 "defaultValue": "",
432 "label": "Name",
433 "type": "Text",
434 "properties": {
435 "fluidAdditionalAttributes": {
436 "placeholder": "Name"
437 }
438 },
439 "__parentRenderable": "example-form/page-1 (filtered)",
440 "__identifierPath": "example-form/page-1/name",
441 "validators": [
442 {
443 "identifier": "NotEmpty"
444 }
445 ]
446 }
447 ]
448 }
449 ]
450 }
451
452 For each form element which has child elements, you will find a property
453 called ``renderables``. Those ``renderables`` are arrays whose elements
454 consists of ``FormElement models`` of the particular child elements.
455
456 As previously mentioned, the ``FormElement model`` is a conglomerate of the
457 data of the ``form definition`` and some additional information:
458
459 - __parentRenderable
460 - __identifierPath
461
462 The following methods can be utilized in order to access the data of a
463 ``FormElement model``:
464
465 - get()
466 - set()
467 - unset()
468 - on()
469 - off()
470 - getObjectData()
471 - toString()
472 - clone()
473
474 For more information, head to the API reference and read the section about
475 the ':ref:`FormElement model<apireference-formeditor-basicjavascriptconcepts-formelementmodel>`'.
476
477
478 .. _concepts-formeditor-translation-formeditor:
479
480 Translation of form editor
481 --------------------------
482
483 All option values which reside below the following configuration keys can be
484 translated:
485
486 .. code-block:: yaml
487
488 TYPO3:
489 CMS:
490 Form:
491 prototypes:
492 standard:
493 formEditor:
494 formElementsDefinition:
495 <formElementTypeIdentifier>:
496 formEditor:
497 finishersDefinition:
498 <finisherIdentifier>
499 formEditor:
500 validatorsDefinition:
501 <validatorIdentifier>
502 formEditor:
503
504 The translation files of the ``form editor`` are loaded as follows:
505
506 .. code-block:: yaml
507
508 TYPO3:
509 CMS:
510 Form:
511 prototypes:
512 standard:
513 formEditor:
514 translationFile:
515 # translation files for the form editor
516 10: 'EXT:form/Resources/Private/Language/Database.xlf'
517 20: 'EXT:my_site_package/Resources/Private/Language/Database.xlf'
518
519 The process searches for each option value within all of the defined
520 translation files. If a translation is found, the translated option value
521 will be used in preference.
522
523 Imagine, the following is defined for an option value:
524
525 .. code-block:: yaml
526
527 ...
528 label: 'formEditor.elements.Form.editor.finishers.label'
529 ...
530
531 First of all, the process searches for the translation key ``formEditor.elements.Form.editor.finishers.label``
532 within the file ``20: 'EXT:my_site_package/Resources/Private/Language/Database.xlf'``
533 and after it inside the file ``10: 'EXT:form/Resources/Private/Language/Database.xlf'``.
534 If nothing is found, the option value will be displayed unmodified.
535
536 Due to compatibility issues, the setting ``translationFile`` is not defined
537 as an array in the default configuration. To load your own translation files,
538 you should define an array containing 'EXT:form/Resources/Private/Language/Database.xlf'
539 as first entry (key ``10``) followed by your own file (key ``20``) as
540 displayed in the example above.