[TASK] Fix broken identifier in form docs
[Packages/TYPO3.CMS.git] / typo3 / sysext / form / Documentation / Concepts / FrontendRendering / Index.rst
1 .. include:: ../../Includes.txt
2
3
4 .. _concepts-frontendrendering:
5
6 Frontend rendering
7 ==================
8
9
10 .. _concepts-frontendrendering-basiccodecomponents:
11
12 Basic code components
13 ---------------------
14
15
16 .. figure:: ../../Images/basic_code_components.png
17    :alt: Basic code components
18
19    Basic code components
20
21
22 .. _concepts-frontendrendering-basiccodecomponents-formdefinition:
23
24 TYPO3\\CMS\\Form\\Domain\\Model\\FormDefinition
25 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
26
27 The class ``TYPO3\\CMS\\Form\\Domain\\Model\\FormDefinition`` encapsulates
28 a complete ``form definition``, with all of its
29
30 - pages,
31 - form elements,
32 - applicable validation rules, and
33 - finishers, which should be executed when the form is submitted.
34
35 The FormDefinition domain model is not modified when the form is executed.
36
37
38 .. _concepts-frontendrendering-basiccodecomponents-formdefinition-anatomy:
39
40 The anatomy of a form
41 +++++++++++++++++++++
42
43 A ``FormDefinition`` domain model consists of multiple ``Page`` objects.
44 When a form is displayed, only one ``Page`` is visible at any given time.
45 Moreover, there is a navigation to go back and forth between those pages. A
46 ``Page`` consists of multiple ``FormElements`` which represent the input
47 fields, textareas, checkboxes, etc. shown on a page. The ``FormDefinition``
48 domain model, ``Page`` and ``FormElement`` objects have ``identifier``
49 properties which must be unique for each given ``<formElementTypeIdentifier>``,
50 i.e. the ``FormDefinition`` domain model and a ``FormElement`` object may
51 have the same ``identifier`` but having the same identifier for two
52 ``FormElement`` objects is disallowed.
53
54
55 .. _concepts-frontendrendering-basiccodecomponents-formdefinition-anatomy-example:
56
57 Example
58 '''''''
59
60 Basically, you can manually create a ``FormDefinition`` domain model just
61 by calling the API methods on it, or you can use a ``FormFactory`` to build
62 the form from a different representation format such as YAML.
63
64 .. code-block:: php
65
66     $formDefinition = $this->objectManager->get(FormDefinition::class, 'myForm');
67
68     $page1 = $this->objectManager->get(Page::class, 'page1');
69     $formDefinition->addPage($page);
70
71     // second argument is the <formElementTypeIdentifier> of the form element
72     $element1 = $this->objectManager->get(GenericFormElement::class, 'title', 'Text');
73     $page1->addElement($element1);
74
75
76 .. _concepts-frontendrendering-basiccodecomponents-formdefinition-createformusingabstracttypes:
77
78 Creating a form using abstract form element types
79 +++++++++++++++++++++++++++++++++++++++++++++++++
80
81 While you can use the ``TYPO3\CMS\Form\Domain\Model\FormDefinition::addPage()``
82 or ``TYPO3\CMS\Form\Domain\Model\FormElements\Page::addElement()`` methods
83 and create the ``Page`` and ``FormElement`` objects manually, it is often
84 better to use the corresponding create* methods (``TYPO3\CMS\Form\Domain\Model\FormDefinition::createPage()``
85 and ``TYPO3\CMS\Form\Domain\Model\FormElements\Page::createElement()``), as
86 you pass them an abstract ``<formElementTypeIdentifier>`` such as ``Text``
87 or ``Page``. EXT:form will automatically resolve the implementation class
88 name and set default values.
89
90 The :ref:`simple example <concepts-frontendrendering-basiccodecomponents-formdefinition-anatomy-example>`
91 shown above should be rewritten as follows:
92
93 .. code-block:: php
94
95     // we will come back to this later on
96     $prototypeConfiguration = [];
97
98     $formDefinition = $this->objectManager->get(FormDefinition::class, 'myForm', $prototypeConfiguration);
99     $page1 = $formDefinition->createPage('page1');
100     $element1 = $page1->addElement('title', 'Text');
101
102 You might wonder how the system knows that the element ``Text`` is
103 implemented by using a ``GenericFormElement``. This is configured in the
104 ``$prototypeConfiguration``. To make the example from above actually work,
105 we need to add some meaningful values to ``$prototypeConfiguration``:
106
107 .. code-block:: php
108
109     $prototypeConfiguration = [
110         'formElementsDefinition' => [
111             'Page' => [
112                 'implementationClassName' => 'TYPO3\CMS\Form\Domain\Model\FormElements\Page'
113             ],
114             'Text' => [
115                 'implementationClassName' => 'TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement'
116             ],
117         ],
118     ];
119
120 For each abstract ``<formElementTypeIdentifier>`` we have to add some
121 configuration. In the snippet above, we only define the ``implementation
122 class name``. Apart form that, it is always possible to set default values
123 for all configuration options of such elements, as the following example
124 shows:
125
126 .. code-block:: php
127
128     $prototypeConfiguration = [
129         'formElementsDefinition' => [
130             'Page' => [
131                 'implementationClassName' => 'TYPO3\CMS\Form\Domain\Model\FormElements\Page',
132                 'label' => 'This is the label of the page if nothing else is specified'
133             ],
134             'Text' => [
135                 'implementationClassName' => 'TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement',
136                 'label' = >'Default Label',
137                 'defaultValue' => 'Default form element value',
138                 'properties' => [
139                     'placeholder' => 'Text that is shown if element is empty'
140                 ],
141             ],
142         ],
143     ];
144
145
146 .. _concepts-frontendrendering-basiccodecomponents-formdefinition-preconfiguredconfiguration:
147
148 Using pre-configured $prototypeConfiguration
149 ++++++++++++++++++++++++++++++++++++++++++++
150
151 Often, it does not make sense to manually create the $prototypeConfiguration
152 array. Bigger parts of this array are pre-configured in the extensions's
153 YAML settings. The ``TYPO3\CMS\Form\Domain\Configuration\ConfigurationService``
154 contains helper methods which return the ready-to-use ``$prototypeConfiguration``.
155
156
157 .. _concepts-frontendrendering-basiccodecomponents-formdefinition-rednering:
158
159 Rendering a FormDefinition
160 ++++++++++++++++++++++++++
161
162 To trigger the rendering of a ``FormDefinition`` domain model, the current
163 ``TYPO3\CMS\Extbase\Mvc\Web\Request`` needs to be bound to the
164 ``FormDefinition``. This binding results in a ``TYPO3\CMS\Form\Domain\Runtime\FormRuntime``
165 object which contains the ``Runtime State`` of the form. Among other things,
166 this object includes the currently inserted values.
167
168 .. code-block:: php
169
170     // $currentRequest and $currentResponse need to be available
171     // inside a controller, you would use $this->request and $this->response;
172     $form = $formDefinition->bind($currentRequest, $currentResponse);
173     // now, you can use the $form object to get information about the currently entered values, etc.
174
175
176 .. _concepts-frontendrendering-basiccodecomponents-formruntime:
177
178 TYPO3\\CMS\\Form\\Domain\\Runtime\\FormRuntime
179 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
180
181 This class implements the runtime logic of a form, i.e. the class
182
183 - decides which page is currently shown,
184 - determines the current values of the form
185 - triggers validation and property mappings.
186
187 You generally receive an instance of this class by calling ``TYPO3\CMS\Form\Domain\Model\FormDefinition::bind()``.
188
189
190 .. _concepts-frontendrendering-basiccodecomponents-formruntime-render:
191
192 Rendering a form
193 ++++++++++++++++
194
195 Rendering a form is easy. Just call ``render()`` on the ``FormRuntime``.
196
197 .. code-block:: php
198
199     $form = $formDefinition->bind($request, $response);
200     $renderedForm = $form->render();
201
202
203 .. _concepts-frontendrendering-basiccodecomponents-formruntime-accessingformvalues:
204
205 Accessing form values
206 +++++++++++++++++++++
207
208 In order to get the values the user has entered into the form, you can
209 access the ``FormRuntime`` object like an array. If a form element with the
210 identifier ``firstName`` exists, you can use ``$form['firstName']`` to
211 retrieve its current value. You can set values the same way.
212
213
214 .. _concepts-frontendrendering-basiccodecomponents-formruntime-renderinginternals:
215
216 Rendering internals
217 +++++++++++++++++++
218
219 The ``FormRuntime`` inquires the ``FormDefinition`` domain model regarding
220 the configured renderer (``TYPO3\CMS\Form\Domain\Model\FormDefinition::getRendererClassName()``)
221 and then triggers render() on this Renderer.
222
223 This allows you to declaratively define how a form should be rendered.
224
225 .. code-block:: yaml
226
227     TYPO3:
228       CMS:
229         Form:
230           prototypes:
231             standard:
232               formElementsDefinition:
233                 Form:
234                   rendererClassName: 'TYPO3\CMS\Form\Domain\Renderer\FluidFormRenderer'
235
236
237 .. _concepts-frontendrendering-basiccodecomponents-fluidformrenderer:
238
239 TYPO3\\CMS\\Form\\Domain\\Renderer\\FluidFormRenderer
240 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
241
242 This class is a  ``TYPO3\CMS\Form\Domain\Renderer\RendererInterface``
243 implementation which used to render a ``FormDefinition`` domain model. It
244 is the default EXT:form renderer.
245
246 Learn more about the :ref:`FluidFormRenderer Options<apireference-frontendrendering-fluidformrenderer-options>`.
247
248
249 .. _concepts-frontendrendering-codecomponents-customformelementimplementations:
250
251 Custom form element implementations
252 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
253
254 EXT:form ships a decent amount of hooks which are available at crucial
255 points of the life cycle of a ``FormElement``. Most of the time, own
256 implementations are therefore unnecessary. An own form element can be
257 defined by:
258
259 - writing some configuration, and
260 - utilizing the standard implementation of ``TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement``.
261
262 .. code-block:: yaml
263
264     TYPO3:
265       CMS:
266         Form:
267           prototypes:
268             standard:
269               formElementsDefinition:
270                 CustomFormElementIdentifier:
271                   implementationClassName: 'TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement'
272
273 With the provided hooks, this ``FormElement`` can now be manipulated.
274
275 If you insist on your own implementation, the abstract class ``TYPO3\CMS\Form\Domain\Model\FormElements\AbstractFormElement``
276 offers a perfect entry point. In addition, we recommend checking-out ``TYPO3\CMS\Form\Domain\Model\Renderable\AbstractRenderable``.
277 All of your own form element implementations must be programmed to the
278 interface ``TYPO3\CMS\Form\Domain\Model\Renderable\RenderableInterface``.
279 It is a good idea to derive your implementation from ``TYPO3\CMS\Form\Domain\Model\FormElements\AbstractFormElement``.
280
281
282 .. _concepts-frontendrendering-codecomponents-customfinisherimplementations:
283
284 Custom finisher implementations
285 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
286
287 Finishers are defined as part of a ``prototype`` within a
288 ``finishersDefinition``. The property ``implementationClassName`` is to be
289 utilized to load the finisher implementation.
290
291 .. code-block:: yaml
292
293     TYPO3:
294       CMS:
295         Form:
296           prototypes:
297             standard:
298               finishersDefinition:
299                 CustomFinisher:
300                   implementationClassName: 'VENDOR\MySitePackage\Domain\Finishers\CustomFinisher'
301
302 If the finisher requires options, you can define those within the
303 ``options`` property. The options will be used as default values and can
304 be overridden using the ``form definition``.
305
306 Define the default value:
307
308 .. code-block:: yaml
309
310     TYPO3:
311       CMS:
312         Form:
313           prototypes:
314             standard:
315               finishersDefinition:
316                 CustomFinisher:
317                   implementationClassName: 'VENDOR\MySitePackage\Domain\Finishers\CustomFinisher'
318                   options:
319                     yourCustomOption: 'Ralf'
320
321 Override the option using the ``form definition``:
322
323 .. code-block:: yaml
324
325     identifier: sample-form
326     label: 'Simple Contact Form'
327     prototype: standard
328     type: Form
329
330     finishers:
331       -
332         identifier: CustomFinisher
333         options:
334           yourCustomOption: 'Bj√∂rn'
335
336     renderables:
337       ...
338
339 Each finisher has to be programmed to the interface ``TYPO3\CMS\Form\Domain\Finishers\FinisherInterface``
340 and should extend the class ``TYPO3\CMS\Form\Domain\Finishers\AbstractFinisher``.
341 In doing so, the logic of the finisher should start with the method
342 ``executeInternal()``.
343
344
345 .. _concepts-frontendrendering-codecomponents-customfinisherimplementations-accessingoptions:
346
347 Accessing finisher options
348 ++++++++++++++++++++++++++
349
350 If your finisher extends ``TYPO3\CMS\Form\Domain\Finishers\AbstractFinisher``,
351 you can access your finisher options with the help of the ``parseOption()``
352 method.
353
354 .. code-block:: php
355
356     $yourCustomOption = $this->parseOption('yourCustomOption');
357
358 ``parseOption()`` is looking for 'yourCustomOption' in your
359 ``form definition``. If it cannot be found, the method checks
360
361 - 1. the ``prototype`` configuration for a default value,
362 - 2. the finisher class itself by searching for a default value within the
363      ``$defaultOptions`` property.
364
365 .. code-block:: php
366
367     <?php
368     declare(strict_types=1);
369     namespace VENDOR\MySitePackage\Domain\Finishers;
370
371     class CustomFinisher extends \TYPO3\CMS\Form\Domain\Finishers\AbstractFinisher
372     {
373
374         protected $defaultOptions = [
375             'yourCustomOption' => 'Olli',
376         ];
377
378         ...
379
380 If the option cannot be found by processing this fallback chain, ``null`` is
381 returned.
382
383 If the option is found, the process checks whether the option value will
384 access :ref:`FormRuntime values<concepts-frontendrendering-codecomponents-customfinisherimplementations-accessingoptions-formruntimeaccessor>`.
385 If the ``FormRuntime`` returns a positive result, it is checked whether the
386 option value :ref:`can access values of preceding finishers<concepts-frontendrendering-codecomponents-customfinisherimplementations-finishercontext-sharedatabetweenfinishers>`.
387 At the very end, it tries to :ref:`translate the finisher options<concepts-frontendrendering-translation-finishers>`.
388
389
390 .. _concepts-frontendrendering-codecomponents-customfinisherimplementations-accessingoptions-formruntimeaccessor:
391
392 Accessing form runtime values
393 '''''''''''''''''''''''''''''
394
395 By utilizing a specific notation, finisher options can be populated with
396 submitted form values (assuming you are using the ``parseOption()`` method).
397 You can access values of the ``FormRuntime`` and thus values of each single
398 form element by encapsulating the option values with ``{}``. If there is a
399 form element with the ``identifier`` 'subject', you can access its value
400 within the the finisher configuration. Check out the following example to
401 get the whole idea.
402
403 .. code-block:: yaml
404
405     identifier: simple-contact-form
406     label: 'Simple Contact Form'
407     prototype: standard
408     type: Form
409
410     finishers:
411       -
412         identifier: Custom
413         options:
414           yourCustomOption: '{subject}'
415
416     renderables:
417       -
418         identifier: subject
419         label: 'Subject'
420         type: Text
421
422
423 .. code-block:: php
424
425     // $yourCustomOption contains the value of the form element with the
426     // identifier 'subject'
427     $yourCustomOption = $this->parseOption('yourCustomOption');
428
429 In addition, you can use ``{__currentTimestamp}`` as a special option value.
430 It will return the current UNIX timestamp.
431
432
433 .. _concepts-frontendrendering-codecomponents-customfinisherimplementations-finishercontext:
434
435 Finisher Context
436 ++++++++++++++++
437
438 The class ``TYPO3\CMS\Form\Domain\Finishers\FinisherContext`` takes care of
439 transferring a finisher context to each finisher. Given the finisher is
440 derived from ``TYPO3\CMS\Form\Domain\Finishers\AbstractFinisher`` the
441 finisher context will be available via
442
443 .. code-block:: php
444
445     $this->finisherContext
446
447 The method ``cancel`` prevents the execution of successive finishers:
448
449 .. code-block:: php
450
451     $this->finisherContext->cancel();
452
453 The method ``getFormValues`` returns all of the submitted form values.
454
455 ``getFormValues``.
456
457 .. code-block:: php
458
459     $this->finisherContext->getFormValues();
460
461 The method ``getFormRuntime`` returns the ``FormRuntime``.
462
463 .. code-block:: php
464
465     $this->finisherContext->getFormRuntime();
466
467
468 .. _concepts-frontendrendering-codecomponents-customfinisherimplementations-finishercontext-sharedatabetweenfinishers:
469
470 Share data between finishers
471 ''''''''''''''''''''''''''''
472
473 The method ``getFinisherVariableProvider`` returns an object (``TYPO3\CMS\Form\Domain\Finishers\FinisherVariableProvider``)
474 which allows you to store data and transfer it to other finishers. The data
475 can be easily accessed programmatically or within your configuration.
476
477 .. code-block:: php
478
479     $this->finisherContext->getFinisherVariableProvider();
480
481 The data is stored within the ``FinisherVariableProvider`` and is addressed
482 by a user-defined 'finisher identifier' and a custom option value path. The
483 name of the 'finisher identifier' should consist of the name of the finisher
484 without the potential 'Finisher' appendix. If your finisher is derived from
485 the class ``TYPO3\CMS\Form\Domain\Finishers\AbstractFinisher``, the name of
486 this construct is stored in the following variable:
487
488 .. code-block:: php
489
490     $this->shortFinisherIdentifier
491
492 For example, if the name of your finisher class is 'CustomFinisher', the
493 mentioned variable will contain the value 'Custom'.
494
495 There are a bunch of methods to access and manage the finisher data:
496
497 - Add data:
498
499   .. code-block:: php
500
501       $this->finisherContext->getFinisherVariableProvider()->add(
502           $this->shortFinisherIdentifier,
503           'unique.value.identifier',
504           $value
505       );
506
507 - Get data:
508
509   .. code-block:: php
510
511       $this->finisherContext->getFinisherVariableProvider()->get(
512           $this->shortFinisherIdentifier,
513           'unique.value.identifier',
514           'default value'
515       );
516
517 - Check the existence of data:
518
519   .. code-block:: php
520
521       $this->finisherContext->getFinisherVariableProvider()->exists(
522           $this->shortFinisherIdentifier,
523           'unique.value.identifier'
524       );
525
526 - Delete data:
527
528   .. code-block:: php
529
530       $this->finisherContext->getFinisherVariableProvider()->remove(
531           $this->shortFinisherIdentifier,
532           'unique.value.identifier'
533       );
534
535 In this way, each finisher can access data programmatically. Moreover, it is
536 possible to retrieve the data via configuration, provided that a finisher
537 stores the values within the ``FinisherVariableProvider``.
538
539 Assuming that a finisher called 'Custom' sets data as follows:
540
541 .. code-block:: php
542
543     $this->finisherContext->getFinisherVariableProvider()->add(
544         $this->shortFinisherIdentifier,
545         'unique.value.identifier',
546         'Wouter'
547     );
548
549 ... you are now able to access the value 'Wouter' via ``{Custom.unique.value.identifier}``
550 in any other finisher.
551
552 .. code-block:: yaml
553
554     identifier: sample-form
555     label: 'Simple Contact Form'
556     prototype: standard
557     type: Form
558
559     finishers:
560       -
561         identifier: Custom
562         options:
563           yourCustomOption: 'Frans'
564
565       -
566         identifier: SomeOtherStuff
567         options:
568           someOtherCustomOption: '{Custom.unique.value.identifier}'
569
570
571 .. _concepts-frontendrendering-codecomponents-customvalidatorimplementations:
572
573 Custom validator implementations
574 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
575
576 Validators belong to a certain ``prototype`` and are defined within the
577 ``validatorsDefinition``. The property ``implementationClassName`` is used
578 for the validator implementation.
579
580 .. code-block:: yaml
581
582     TYPO3:
583       CMS:
584         Form:
585           prototypes:
586             standard:
587               validatorsDefinition:
588                 Custom:
589                   implementationClassName: 'VENDOR\MySitePackage\Domain\Validation\CustomValidator'
590
591 You can provide options for your validator using the property ``options``.
592 Those will be used as default values which can be overridden within a
593 specific ``form definition``.
594
595 Define the default value of the option ``yourCustomOption``:
596
597 .. code-block:: yaml
598
599     TYPO3:
600       CMS:
601         Form:
602           prototypes:
603             standard:
604               validatorsDefinition:
605                 Custom:
606                   implementationClassName: 'VENDOR\MySitePackage\Domain\Validation\CustomValidator'
607                   options:
608                     yourCustomOption: 'Jurian'
609
610 Override the default value within your ``form definition``:
611
612 .. code-block:: yaml
613
614     identifier: sample-form
615     label: 'Simple Contact Form'
616     prototype: standard
617     type: Form
618
619     renderables:
620       -
621         identifier: subject
622         label: 'Name'
623         type: Text
624         validators:
625           -
626             identifier: Custom
627             options:
628               yourCustomOption: 'Mathias'
629
630 EXT:form implements Extbase validators. That said, your own validators should
631 extend ``TYPO3\CMS\Extbase\Validation\Validator\AbstractValidator``.
632
633
634 .. _concepts-frontendrendering-renderviewHelper:
635
636 "render" viewHelper
637 -------------------
638
639 The ``RenderViewHelper`` is the actual starting point for form rendering and
640 not the typical Extbase Controller as you may know it.
641
642 For more technical insights read more about the viewHelper's :ref:`arguments<apireference-frontendrendering-renderviewHelper-arguments>`.
643
644
645 .. _concepts-frontendrendering-fluidtemplate:
646
647 Render through FLUIDTEMPLATE (without controller)
648 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
649
650 .. code-block:: typoscript
651
652     tt_content.custom_content_element = COA_INT
653     tt_content.custom_content_element {
654         10 = < lib.stdheader
655         20 = FLUIDTEMPLATE
656         20 {
657             file = EXT:my_site_package/Resources/Private/Templates/CustomContentElement.html
658             settings {
659                 persistenceIdentifier = EXT:my_site_package/Resources/Private/Forms/MyForm.yaml
660             }
661             extbase.pluginName = Form
662             extbase.controllerExtensionName = Formframework
663             extbase.controllerName = FormFrontend
664             extbase.controllerActionName = perform
665         }
666     }
667
668 ``my_site_package/Resources/Private/Templates/CustomContentElement.html``:
669
670 .. code-block:: html
671
672     <formvh:render persistenceIdentifier="{settings.persistenceIdentifier}" />
673
674
675 .. _concepts-frontendrendering-extbase:
676
677 Render within your own Extbase extension
678 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
679
680 It is straight forward. Use the ``RenderViewHelper`` like this and you are
681 done:
682
683 .. code-block:: html
684
685     <formvh:render persistenceIdentifier="EXT:my_site_package/Resources/Private/Forms/MyForm.yaml"/>
686
687 Point the property ``controllerAction`` to the desired action name and
688 provide values for the other parameters displayed below (you might need
689 those).
690
691 .. code-block:: yaml
692
693     type: Form
694     identifier: 'example-form'
695     label: 'TYPO3 is cool'
696     prototypeName: standard
697     renderingOptions:
698       controllerAction: perform
699       addQueryString: false
700       argumentsToBeExcludedFromQueryString: []
701       additionalParams: []
702
703     renderables:
704       ...
705
706
707 .. _concepts-frontendrendering-programmatically:
708
709 Build forms programmatically
710 ----------------------------
711
712 To learn more about this topic, head to the chapter ':ref:`Build forms programmatically<apireference-frontendrendering-programmatically>`'
713 which is part of the API reference section.
714
715
716 .. _concepts-frontendrendering-runtimemanipulation:
717
718 Runtime manipulation
719 --------------------
720
721 .. _concepts-frontendrendering-runtimemanipulation-hooks:
722
723 Hooks
724 ^^^^^
725
726 EXT:form implements a decent amount of hooks that allow the manipulation of
727 your forms during runtime. In this way, it is possible to, for example,
728
729 - ... prefill form elements with values from your database,
730 - ... skip a whole page based on the value of a certain form element,
731 - ... mark a form element as mandatory depending of the chosen value of another
732   form element.
733
734 Please check out the ':ref:`API reference section<apireference-frontendrendering-runtimemanipulation-hooks>`'
735 for more details.
736
737
738 .. _concepts-frontendrendering-runtimemanipulation-typoscriptoverrides:
739
740 TypoScript overrides
741 ^^^^^^^^^^^^^^^^^^^^
742
743 Each and every ``form definition`` can be overridden via TypoScript if the
744 ``FormFrontendController`` of EXT:form is used to render the form. Normally,
745 this is the case if the form has been added to the page using the form
746 plugin or when rendering the form via :ref:`FLUIDTEMPLATE <concepts-frontendrendering-fluidtemplate>`.
747
748 The overriding of settings with TypoScript's help takes place after the :ref:`custom finisher settings<concepts-formplugin>`
749 of the form plugin have been loaded. In this way, you are able to manipulate
750 the ``form definition`` for a single page. In doing so, the altered
751 ``form definition`` is passed to the ``RenderViewHelper`` which then
752 generates the form programmatically. At this point, you can still change the
753 form elements using the above-mentioned concept of :ref:`hooks<concepts-frontendrendering-runtimemanipulation-hooks>`.
754
755 .. code-block:: typoscript
756
757     plugin.tx_form {
758         settings {
759             formDefinitionOverrides {
760                 <formDefinitionIdentifier> {
761                     renderables {
762                         0 {
763                             renderables {
764                                 0 {
765                                     label = TEXT
766                                     label.value = Overridden label
767                                 }
768                             }
769                         }
770                     }
771                 }
772             }
773         }
774     }
775
776
777 .. _concepts-frontendrendering-templates:
778
779 Templates
780 ---------
781
782 The Fluid templates of the form framework are based on Twitter Bootstrap.
783
784
785 .. _concepts-frontendrendering-templates-customtemplates:
786
787 Custom templates
788 ^^^^^^^^^^^^^^^^
789
790 If you want to use custom Fluid templates for the frontend output of the
791 form elements, you cannot register an additional template path using
792 TypoScript. Instead, the registration of new template paths has to be done
793 via YAML. The settings are part of the ``prototypes`` configuration.
794
795 .. code-block:: yaml
796
797     TYPO3:
798       CMS:
799         Form:
800           prototypes:
801             standard:
802               formElementsDefinition:
803                 Form:
804                   renderingOptions:
805                     templateRootPaths:
806                       100: 'EXT:my_site_package/Resources/Private/Frontend/Templates/'
807                     partialRootPaths:
808                       100: 'EXT:my_site_package/Resources/Private/Frontend/Partials/'
809                     layoutRootPaths:
810                       100: 'EXT:my_site_package/Resources/Private/Frontend/Layouts/'
811
812 For each ``form definition`` - which references the prototype ``standard`` -
813 the form framework will additionally look for Fluid templates within the
814 path 'EXT:my_site_package/Resources/Private/Frontend/[*]' as set above.
815 Apart from the 'Form' element, the process will search for templates within
816 the ``partialRootPaths`` folder. The name of the partial is derived from the
817 property ``formElementTypeIdentifier``. For example, the template of the
818 form element ``Text`` must be stored within the ``partialRootPaths`` folder
819 named ``Text.html``. In contrast, the template of the ``Form`` element must
820 reside within the ``templateRootPaths`` folder. According to the introduced
821 logic, the template name must be ``Form.html``.
822
823
824 .. _concepts-frontendrendering-translation:
825
826 Translation
827 -----------
828
829 .. _concepts-frontendrendering-translation-formdefinition:
830
831 Translate form definition
832 ^^^^^^^^^^^^^^^^^^^^^^^^^
833
834 The translation of ``form definitions`` works differently to the translation
835 of the backend aspects. Currently, there is no graphical user interface
836 supporting the translation process.
837
838 If the backend editor needed to translate the ``form definition`` properties
839 in the same way the backend aspects are translated, he/ she would see long
840 and unwieldy translation keys while editing a form within the ``form editor``.
841 In order to avoid this, rather the element properties are translated than
842 their values. Thus, the form framework does not look for translation keys
843 within the translation file. Instead, the system searches for translations
844 of the form element properties independent of their property values. The
845 property values are ignored if the process finds a proper entry within the
846 translation file. As a result, the property values are overridden by the
847 translated value.
848
849 This approach is a compromise between two scenarios: the exclusive usage of
850 the ``form editor`` and/ or the manual creation of ``form definitions``
851 which can afterwards (theoretically) be edited with the ``form editor``. In
852 addition, the described compromise allows the editor to create forms in the
853 default language whose form element property values are displayed as
854 specified in the ``form editor``. Based on this, an integrator could provide
855 additional language files which automatically translate the specific form.
856
857 Additional translation files can be defined as follows:
858
859 .. code-block:: yaml
860
861     TYPO3:
862       CMS:
863         Form:
864           prototypes:
865             standard:
866               formElementsDefinition:
867                 Form:
868                   renderingOptions:
869                     translation:
870                       translationFile:
871                         # translation files for the frontend
872                         10: 'EXT:form/Resources/Private/Language/locallang.xlf'
873                         20: 'EXT:my_site_package/Resources/Private/Language/locallang.xlf'
874
875 Due to compatibility issues, the setting ``translationFile`` is not defined
876 as an array in the default configuration. To load your own translation files,
877 you should define an array containing 'EXT:form/Resources/Private/Language/locallang.xlf'
878 as first entry (key ``10``) followed by your own file (key ``20``) as
879 displayed in the example above. The array is processed from the highest key
880 to the lowest, i.e. your translation file with the key ``20`` is processed
881 first. If the look-up process does not find a key within all of the provided
882 files, the property value will be displayed unmodified.
883
884 The following properties can be translated:
885
886 - label
887 - properties.[*]
888 - properties.options.[*]
889 - properties.fluidAdditionalAttributes.[*]
890 - renderingOptions.[*]
891
892 The translation keys are put together based on a specific pattern. In
893 addition, a fallback chain that depends on the form element identifiers
894 exists. As a result, the following translation scenarios are possible:
895
896 - translation of a form element property for a specific form and form
897   element
898 - translation of a form element property for a specific form element and
899   various forms
900 - translation of a form element property for an element type and various
901   forms, e.g. the ``Page`` element
902
903 The look-up process searches for translation keys in all given translation
904 files based on the following order:
905
906 - ``<formDefinitionIdentifier>.element.<elementIdentifier>.properties.<propertyName>``
907 - ``element.<formElementIdentifier>.properties.<propertyName>``
908 - ``element.<elementType>.properties.<propertyName>``
909
910 Form elements with option properties (``properties.options``), like the
911 ``Select`` element, feature the following look-up process:
912
913 - ``<formDefinitionIdentifier>.element.<elementIdentifier>.properties.options.<propertyValue>``
914 - ``element.<elementIdentifier>.properties.options.<propertyValue>``
915
916
917 Example
918 +++++++
919
920 .. code-block:: yaml
921
922     identifier: ApplicationForm
923     type: Form
924     prototypeName: standard
925     label: 'Application form'
926
927     renderables:
928       -
929         identifier: GeneralInformation
930         type: Page
931         label: 'General information'
932
933         renderables:
934           -
935             identifier: LastName
936             type: Text
937             label: 'Last name'
938             properties:
939               placeholder: 'Please enter your last name.'
940             defaultValue: ''
941           -
942             identifier: Software
943             type: MultiSelect
944             label: 'Known software'
945             properties:
946               options:
947                 value1: TYPO3
948                 value2: Neos
949
950 For the form element ``LastName``, the process will look for the following
951 translation keys within the translation files:
952
953 - ``ApplicationForm.element.LastName.properties.label``
954 - ``element.LastName.properties.label``
955 - ``element.Text.properties.label``
956
957 If none of the above-mentioned keys exist, 'Last name' will be displayed.
958
959 For the form element ``Software``, the process will look for the following
960 translation keys within the translation files:
961
962 - ``ApplicationForm.element.Software.properties.label``
963 - ``element.Software.properties.label``
964 - ``element.MultiSelect.properties.label``
965
966 If none of the above-mentioned keys exist, 'Known software' will be
967 displayed. The option properties are addressed as follows:
968
969 - ``ApplicationForm.element.Software.properties.options.value1``
970 - ``element.Software.properties.options.value1``
971 - ``ApplicationForm.element.Software.properties.options.value2``
972 - ``element.Software.properties.options.value2``
973
974 If none of the above-mentioned keys exist, 'TYPO3' will be displayed as
975 label for the first option and 'Neos' as label for the second option.
976
977
978 .. _concepts-frontendrendering-translation-validationerrors:
979
980 Translation of validation messages
981 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
982
983 The translation of validation messages is similar to the translation of
984 ``form definitions``. The same translation files can be used. If the look-up
985 process does not find a key within the provided files, the appropriate
986 message of the Extbase framework will be displayed. EXT:form already
987 translates all of those validators by default.
988
989 As mentioned above, the translation keys are put together based on a
990 specific pattern. Furthermore, the fallback chain exists here as well. Thus,
991 the following translation scenarios are possible:
992
993 - translation of validation messages for a specific validator of a concrete
994   form element and form
995 - translation of validation messages for a specific validator of various
996   form elements within a concrete form
997 - translation of validation messages for a specific validator within various
998   forms
999
1000 In Extbase, the validation messages are identified with the help of
1001 numerical codes (UNIX timestamps). For the same validator, different codes
1002 are valid. Read more about :ref:`concrete validator configurations <typo3.cms.form.prototypes.\<prototypeidentifier>.validatorsdefinition.\<validatoridentifier>-concreteconfigurations>`.
1003
1004 The look-up process searches for translation keys in all given translation
1005 files based on the following order:
1006
1007 - ``<formDefinitionIdentifier>.validation.<elementIdentifier>.<validationErrorCode>``
1008 - ``<formDefinitionIdentifier>.validation.<validationErrorCode>``
1009 - ``validation.<validationErrorCode>``
1010
1011
1012 Example
1013 +++++++
1014
1015 .. code-block:: yaml
1016
1017     identifier: ContactForm
1018     type: Form
1019     prototypeName: standard
1020     label: 'Contact us'
1021
1022     renderables:
1023       -
1024         identifier: Page1
1025         type: Page
1026         label: 'Page 1'
1027
1028         renderables:
1029           -
1030             identifier: LastName
1031             type: Text
1032             label: 'Last name'
1033             properties:
1034               fluidAdditionalAttributes:
1035                 required: required
1036             validators:
1037               -
1038                 identifier: NotEmpty
1039
1040 Amongst others, the ``NotEmpty`` validator sends 1221560910 as ``<validationErrorCode>``.
1041 If a user submits this form without providing a value for the field "Last
1042 name", the ``NotEmpty`` validator fails. Now, the look-up process searches
1043 for the following translation keys for the ``NotEmpty`` validator combined
1044 with the form element ``LastName``:
1045
1046 - ContactForm.validation.LastName.1221560910
1047 - ContactForm.validation.1221560910
1048 - validation.1221560910
1049
1050 As mentioned above, if there is no corresponding translation key available,
1051 the default message of the Extbase framework will be shown.
1052
1053
1054 .. _concepts-frontendrendering-translation-finishers:
1055
1056 Translation of finisher options
1057 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1058
1059 The translation of finisher options is similar to the translation of
1060 ``form definitions``. The same translation files can be used. If the look-up
1061 process does not find a key within all provided files, the property value
1062 will be displayed unmodified.
1063
1064 As mentioned above, the translation keys are put together based on a
1065 specific pattern. Furthermore, the fallback chain exists here as well. Thus,
1066 the following translation scenarios are possible:
1067
1068 - translation of finisher options for a specific finisher of a concrete form
1069 - translation of finisher options for a specific finisher of various forms
1070
1071 The look-up process searches for translation keys in all given translation
1072 files based on the following order:
1073
1074 - ``<formDefinitionIdentifier>.finisher.<finisherIdentifier>.<optionName>``
1075 - ``finisher.<finisherIdentifier>.<optionName>``
1076
1077
1078 Example
1079 +++++++
1080
1081 .. code-block:: yaml
1082
1083     identifier: ContactForm
1084     type: Form
1085     prototypeName: standard
1086     label: 'Contact us'
1087
1088     finishers:
1089       -
1090         identifier: Confirmation
1091         options:
1092           message: 'Thank you for your inquiry.'
1093
1094     renderables:
1095       ...
1096
1097 The look-up process searches for the following translation keys for the
1098 ``<finisherIdentifier>`` 'Confirmation' and the option 'message':
1099
1100 - ``ContactForm.finisher.Confirmation.message``
1101 - ``finisher.Confirmation.message``
1102
1103 If no translation key exists, the message 'Thank you for your inquiry.' will
1104 be shown.