Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 72 additions & 18 deletions Documentation/Global/Form/Index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,38 +9,92 @@ Form ViewHelper `<f:form>`

.. typo3:viewhelper:: form
:source: /Global.json
:display: tags,description,gitHubLink,arguments
:display: tags,description,gitHubLink
:noindex:

.. include:: /_Includes/_ExtbaseFormViewHelpers.rst.txt

.. contents:: Table of contents

.. _typo3-fluid-form-example:

Examples
========
Array parameter passed to Extbase controller action
===================================================

For example a very simplified search form could look like this:

.. literalinclude:: _codesnippets/_PlainParameterForm.html
:caption: packages/my_extension/Resources/Private/Templates/Search/SearchForm.html

The `Extbase controller <https://docs.typo3.org/permalink/t3coreapi:extbase-controller>`_
action could for example look like this:

.. literalinclude:: _codesnippets/_SearchController.php
:caption: packages/my_extension/Classes/Controller/SearchController.php

.. _typo3-fluid-form-example-property:

Property mapping - using the form with a model
==============================================

In most cases you will use the f:form ViewHelper with
`Extbase models <https://docs.typo3.org/permalink/t3coreapi:extbase-model>`_ or
data objects.

For example, user could add a comment in such a form:

A complex form with a specified encoding type
---------------------------------------------
.. literalinclude:: _codesnippets/_CommentForm.html
:caption: packages/my_extension/Resources/Private/Templates/Comment/_CommentForm.html

Form with enctype set::
The Extbase Controller action displaying the form then creates the Domain object
and passes it to the view. In the Fluid template above we use argument
:ref:`object <t3viewhelper:viewhelper-argument-typo3-cms-fluid-viewhelpers-formviewhelper-object>`
to pass any data the object might already contain to the ViewHelper.

<f:form action=".." controller="..." package="..." enctype="multipart/form-data">...</f:form>
By using the argument "property" on the form input elements the properties of
the model are automatically bound to the input elements.

A Form which should render a domain object
------------------------------------------
The controller could look like this:

Binding a domain object to a form::
.. literalinclude:: _codesnippets/_CommentController.php
:caption: packages/my_extension/Classes/Controller/CommentController.php

<f:form action="..." name="customer" object="{customer}">
<f:form.hidden property="id" />
<f:form.textarea property="name" />
</f:form>
If the model is not valid (see `Validation <https://docs.typo3.org/permalink/t3coreapi:extbase-validation>`_)
Extbase will automatically refer the request back to the referring action
(here commentFormAction()). By passing the object with the non-validated object
to the view again, the user can see their faulty inputs and correct them instead
of seeing an empty form.

This automatically inserts the value of ``{customer.name}`` inside the
textarea and adjusts the name of the textarea accordingly.
.. _typo3-fluid-form-security:

Security in Fluid forms
=======================

Fluid automatically adds a hidden field to forms, including an `__hmac`
value. This value lists all allowed fields. If fields are added or
removed via attacks, Extbase detects the mismatch and blocks submission.

Form fields can be grouped in an array for efficient processing. The
receiving action maps the data to a model, where validation occurs if
rules are defined. Only valid data is passed to the action and stored in
the database.

.. _typo3-fluid-form-arguments:

Arguments of the form ViewHelper
================================

.. include:: /_Includes/_ArbitraryArguments.rst.txt

.. typo3:viewhelper:: form
:source: /Global.json
:display: arguments-only


.. _typo3-fluid-form-viewhelpers:

ViewHelpers to be used within the form ViewHelper
=================================================
ViewHelpers for form input elements
===================================

.. toctree::
:titlesonly:
Expand Down
19 changes: 19 additions & 0 deletions Documentation/Global/Form/_codesnippets/Comment.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

declare(strict_types=1);

namespace MyVendor\MyExtension\Domain\Model;

use TYPO3\CMS\Extbase\Annotation\Validate;
use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;

class Comment extends AbstractEntity
{
#[Validate(['validator' => 'EmailAddress'])]
protected string $email = '';

#[Validate(['validator' => 'StringLength', 'options' => ['maximum' => 500]])]
protected string $content = '';

// Getters and setters ...
}
39 changes: 39 additions & 0 deletions Documentation/Global/Form/_codesnippets/_CommentController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

declare(strict_types=1);

namespace MyVendor\MyExtension\Controller;

use Psr\Http\Message\ResponseInterface;
use T3docs\BlogExample\Domain\Model\Comment;
use T3docs\BlogExample\Domain\Repository\CommentRepository;
use TYPO3\CMS\Extbase\Annotation\IgnoreValidation;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;

class CommentController extends ActionController
{
public function __construct(
protected readonly CommentRepository $commentRepository,
) {}

#[IgnoreValidation(['argumentName' => 'newComment'])]
public function commentFormAction(?Comment $newComment = null): ResponseInterface
{
if ($newComment === null) {
$newComment = new Comment();
$newComment->setDate(new \DateTime());
}
// The assigned object will be used in argument object
$this->view->assign('newComment', $newComment);
return $this->htmlResponse();
}

public function createAction(
// This parameter must have the same name as argument `objectName` of f:form
Comment $comment,
): ResponseInterface {
$this->commentRepository->add($comment);
$this->addFlashMessage('Comment was saved');
return $this->redirect('show');
}
}
16 changes: 16 additions & 0 deletions Documentation/Global/Form/_codesnippets/_CommentForm.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
data-namespace-typo3-fluid="true">
<f:form action="create" controller="Comment" objectName="comment" object="{newComment}" method="post">
<div>
<label for="tx-blogexample-email">E-Mail::</label>
<f:form.textfield property="email" type="email" id="tx-blogexample-email"/>
</div>
<div>
<label for="tx-blogexample-content">Message:</label>
<f:form.textarea property="content" id="tx-blogexample-content" rows="8" cols="46"/>
</div>
<div>
<f:form.submit class="button" value="Submit"/>
</div>
</f:form>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<f:form action="search" method="post" pageUid="{settings.targetPid}">
<div>
<label for="sword">Search:</label>
<f:form.textfield name="search[sword]" value="{sword}" id="sword" />
</div>
<div>
<f:form.submit name="search[submitButton]" value="Submit" />
</div>
</f:form>
17 changes: 17 additions & 0 deletions Documentation/Global/Form/_codesnippets/_SearchController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

declare(strict_types=1);

namespace MyVendor\MyExtension\Controller;

use Psr\Http\Message\ResponseInterface;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;

class SearchController extends ActionController
{
public function searchAction(array $search = []): ResponseInterface
{
// TODO: implement search
return $this->htmlResponse();
}
}
4 changes: 4 additions & 0 deletions Documentation/_Includes/_ArbitraryArguments.rst.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.. admonition:: Allows arbitrary arguments

This ViewHelper allows you to pass arbitrary arguments not defined below
directly to the HTML tag created. This includes custom `data-` arguments.
7 changes: 7 additions & 0 deletions Documentation/_Includes/_ExtbaseFormViewHelpers.rst.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.. attention::
.. versionchanged:: 12.0
The f:form ViewHelpers can only be used within the Extbase context.

In a non-Extbase context, for example within a
`FLUIDTEMPLATE <https://docs.typo3.org/permalink/t3tsref:cobj-template>`_
Use plain HTML `<form>` and `<input>` tags.