[TASK] Fix broken validation translation 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.error.<elementIdentifier>.<validationErrorCode>``
1008 - ``<formDefinitionIdentifier>.validation.error.<validationErrorCode>``
1009 - ``validation.error.<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.error.LastName.1221560910
1047 - ContactForm.validation.error.1221560910
1048 - validation.error.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.