---
title: "Form ViewHelper <f:form>"
manual: "Fluid ViewHelper Reference"
version: "13.4"
permalink: "https://docs.typo3.org/permalink/t3viewhelper:typo3-fluid-form@13.4"
source: "Global/Form/Index.rst"
modified: "2026-09-17T09:07:45+00:00"
---

# Form ViewHelper `<f:form>`

ViewHelper to generate a `<form>` tag and prepare context for further `<f:form>` ViewHelpers within that form. Tailored for Extbase plugins, uses Extbase Request.

Go to the source code of this ViewHelper: [FormViewHelper.php (GitHub)](https://github.com/TYPO3/typo3/blob/main/typo3/sysext/fluid/Classes/ViewHelpers/FormViewHelper.php).

> [!WARNING]
> **Attention**
>
> > [!NOTE]
> > **Changed in version 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/m/typo3/reference-typoscript/13.4/en-us/ContentObjects/Fluidtemplate/Index.html#cobj-template)
> > Use plain HTML `<form>` and `<input>` tags.

**Table of contents**

-   [Array parameter passed to Extbase controller action](https://docs.typo3.org/permalink/t3viewhelper:array-parameter-passed-to-extbase-controller-action@13.4)
-   [Property mapping - using the form with a model](https://docs.typo3.org/permalink/t3viewhelper:property-mapping-using-the-form-with-a-model@13.4)
-   [Security in Fluid forms](https://docs.typo3.org/permalink/t3viewhelper:security-in-fluid-forms@13.4)
-   [Using f:form.<somefield> in Fluid components](https://docs.typo3.org/permalink/t3viewhelper:using-f-form-somefield-in-fluid-components@13.4)
-   [Arguments of the form ViewHelper](https://docs.typo3.org/permalink/t3viewhelper:arguments-of-the-form-viewhelper@13.4)
-   [ViewHelpers for form input elements](https://docs.typo3.org/permalink/t3viewhelper:viewhelpers-for-form-input-elements@13.4)

## Array parameter passed to Extbase controller action

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

**packages/my_extension/Resources/Private/Templates/Search/SearchForm.html**

```html
<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>

```

The [Extbase controller](https://docs.typo3.org/m/typo3/reference-coreapi/13.4/en-us/ExtensionArchitecture/Extbase/Reference/Controller/Index.html#extbase-controller)
action could for example look like this:

**packages/my_extension/Classes/Controller/SearchController.php**

```php
<?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();
  }
}

```

## 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/m/typo3/reference-coreapi/13.4/en-us/ExtensionArchitecture/Extbase/Reference/Domain/Model/Index.html#extbase-model) or
data objects.

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

**packages/my_extension/Resources/Private/Templates/Comment/CommentForm.html**

```html
<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">

        <label for="tx-blogexample-email">E-Mail:</label>
        <f:form.textfield property="email"
                          type="email"
                          id="tx-blogexample-email" />

        <label for="tx-blogexample-content">Message:</label>
        <f:form.textarea property="content"
                         id="tx-blogexample-content"
                         rows="8"
                         cols="46" />

        <f:form.submit class="button"
                       value="Submit" />

</f:form>
</html>

```

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
[object](https://docs.typo3.org/permalink/t3viewhelper:viewhelper-argument-typo3-cms-fluid-viewhelpers-formviewhelper-object@13.4)
to pass any data the object might already contain to the ViewHelper.

By using the argument "property" on the form input elements the properties of
the model are automatically bound to the input elements.

The controller could look like this:

**packages/my_extension/Classes/Controller/CommentController.php**

```php
<?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');
  }
}

```

If the model is not valid (see [Validation](https://docs.typo3.org/m/typo3/reference-coreapi/13.4/en-us/ExtensionArchitecture/Extbase/Reference/Validation/Index.html#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.

## Security in Fluid forms

Fluid automatically adds several hidden field to forms:

-   `__referrer[]` with an array of items `@extension`, `@controller`,
    `@action`, `arguments` and `@request`. This holds information about
    where the form has been created, so that in case of errors,
    redirection to the originating Extbase controller and action
    (and extension) is possible.
-   `__trustedProperties` (string) holds information about all used properties
    of all Extbase domain models that have been utilized within the
    related `<f:form>` context. This is used to ensure only properties
    will be evaluated for persistence that have an editable form field
    associated with them.

To prevent tampering with this vital data, the important fields
(`__referrer[arguments]`, `__referrer[@request]`, `__trustedProperties`)
are signed with the private TYPO3 encryption key using an HMAC
hash.

An example would look like this:

**Example HTML rendered after Fluid processing**

```html
<form action="/admin/update?token=328190ab378fe49af07d8b6b4ec31f87bd910efc" method="post">
  <div>
    <input type="hidden" name="__referrer[@extension]" value="Beuser">
    <input type="hidden" name="__referrer[@controller]" value="BackendUser">
    <input type="hidden" name="__referrer[@action]" value="list">
    <input type="hidden" name="__referrer[arguments]" value="YTozOntzOjEwOiJjb250cm9sbGVyIjtzOjExOiJCYWNrZW5kVXNlciI7czo2OiJhY3Rpb24iO3M6NToiaW5kZXgiO3M6NToidG9rZW4iO3M6NDA6IjgxNWZhOGI0OGYyZDg0N2NkMzcwYWIzYTkyMjhlNDY2OWI4OTI0MmUiO30=b305f0773528375502f167cde7c6c63f6ba988f9">
    <input type="hidden" name="__referrer[@request]" value="{&quot;@extension&quot;:&quot;Beuser&quot;,&quot;@controller&quot;:&quot;BackendUser&quot;,&quot;@action&quot;:&quot;list&quot;}51b024523b594011fa9054f7fc82c03ead78061b">
    <input type="hidden" name="__trustedProperties" value="{&quot;demand&quot;:{&quot;userName&quot;:1,&quot;userType&quot;:1,&quot;status&quot;:1,&quot;logins&quot;:1,&quot;backendUserGroup&quot;:1},&quot;operation&quot;:1}c25fc9eb44fc0e40e8ec5cf39fc5d21022172ebf">
  </div>
</form>
```

If form fields are added or removed via attacks, Extbase detects the
mismatch and blocks further processing.

Form fields can be grouped in an array for efficient processing. An
internal Extbase processing action maps the received data to a model,
where (optional and configurable) validation occurs.
Only valid data is passed on to the action and stored in
the database.

## Using f:form.\<somefield> in Fluid components

> [!WARNING]
> Form input fields like the [Form.textfield ViewHelper \<f:form.textfield>](https://docs.typo3.org/permalink/t3viewhelper:typo3-fluid-form-textfield@13.4)
> need to find their parent form `<f:form>` within the rendering context.
>
> They cannot be used in Fluid Components in TYPO3 13.4.

In [Components](https://docs.typo3.org/permalink/fluid:components)
(introduced with Fluid 4.3) a new rendering context is created for
each Fluid component. Therefore form fields loose the connection
to their parent form and cannot be used.

It is however possible to pass a form field to a slot:

**packages/my_extension/Resources/Private/Components/FormField/FormField.html**

```html
<f:argument name="id" type="string" />
<f:argument name="label" type="string" />

<div class="mb-3">
    <label for="{id}" class="form-label">{label}</label>
    <f:slot />
</div>

```

And then use it like this:

```html
<my:inputWithLabel id="abc" label="My label">
    <f:input id="abc" property="myProperty"
<my:inputWithLabel>
```

## Arguments of the form ViewHelper

> **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.

-   **absolute**

    -   *Type:* bool
    -   *Default:* false

    If set, an absolute action URI is rendered (only active if $actionUri is not set)

-   **action**

    -   *Type:* string

    Target action

-   **actionUri**

    -   *Type:* string

    can be used to overwrite the "action" attribute of the form tag

-   **addQueryString**

    -   *Type:* string
    -   *Default:* false

    If set, the current query parameters will be kept in the URL. If set to "untrusted", then ALL query parameters will be added. Be aware, that this might lead to problems when the generated link is cached.

-   **additionalAttributes**

    -   *Type:* array

    Additional tag attributes. They will be added directly to the resulting HTML tag.

-   **additionalParams**

    -   *Type:* array
    -   *Default:* array (
    )

    additional action URI query parameters that won't be prefixed like $arguments (overrule $arguments) (only active if $actionUri is not set)

-   **arguments**

    -   *Type:* array
    -   *Default:* array (
    )

    Arguments (do not use reserved keywords "action", "controller" or "format" if not referring to these internal variables specifically)

-   **argumentsToBeExcludedFromQueryString**

    -   *Type:* array
    -   *Default:* array (
    )

    arguments to be removed from the action URI. Only active if $addQueryString = TRUE and $actionUri is not set

-   **aria**

    -   *Type:* array

    Additional aria-\* attributes. They will each be added with a "aria-" prefix.

-   **controller**

    -   *Type:* string

    Target controller

-   **data**

    -   *Type:* array

    Additional data-\* attributes. They will each be added with a "data-" prefix.

-   **extensionName**

    -   *Type:* string

    Target Extension Name (without \`tx\_\` prefix and no underscores). If NULL the current extension name is used

-   **fieldNamePrefix**

    -   *Type:* string

    Prefix that will be added to all field names within this form. If not set the prefix will be tx_yourExtension_plugin

-   **format**

    -   *Type:* string
    -   *Default:* ''

    The requested format (e.g. ".html") of the target page (only active if $actionUri is not set)

-   **hiddenFieldClassName**

    -   *Type:* string

    hiddenFieldClassName

-   **method**

    -   *Type:* string
    -   *Default:* 'post'

    Transfer type (get or post)

-   **name**

    -   *Type:* string

    Name of form

-   **noCache**

    -   *Type:* bool
    -   *Default:* false

    set this to disable caching for the target page. You should not need this.

-   **novalidate**

    -   *Type:* bool

    Indicate that the form is not to be validated on submit.

-   **object**

    -   *Type:* mixed

    Object to use for the form. Use in conjunction with the "property" attribute on the sub tags

-   **objectName**

    -   *Type:* string

    name of the object that is bound to this form. If this argument is not specified, the name attribute of this form is used to determine the FormObjectName

-   **pageType**

    -   *Type:* int
    -   *Default:* 0

    Target page type

-   **pageUid**

    -   *Type:* int

    Target page uid

-   **pluginName**

    -   *Type:* string

    Target plugin. If empty, the current plugin name is used

-   **requestToken**

    -   *Type:* mixed

    whether to add that request token to the form

-   **section**

    -   *Type:* string
    -   *Default:* ''

    The anchor to be added to the action URI (only active if $actionUri is not set)

-   **signingType**

    -   *Type:* string

    which signing type to be used on the request token (falls back to "nonce")

## ViewHelpers for form input elements

-   [form.button](https://docs.typo3.org/permalink/t3viewhelper:typo3-fluid-form-button@13.4)
-   [form.checkbox](https://docs.typo3.org/permalink/t3viewhelper:typo3-fluid-form-checkbox@13.4)
-   [form.countrySelect](https://docs.typo3.org/permalink/t3viewhelper:typo3-fluid-form-countryselect@13.4)
-   [form.hidden](https://docs.typo3.org/permalink/t3viewhelper:typo3-fluid-form-hidden@13.4)
-   [form.password](https://docs.typo3.org/permalink/t3viewhelper:typo3-fluid-form-password@13.4)
-   [form.radio](https://docs.typo3.org/permalink/t3viewhelper:typo3-fluid-form-radio@13.4)
-   [form.select](https://docs.typo3.org/permalink/t3viewhelper:typo3-fluid-form-select@13.4)
-   [form.submit](https://docs.typo3.org/permalink/t3viewhelper:typo3-fluid-form-submit@13.4)
-   [form.textarea](https://docs.typo3.org/permalink/t3viewhelper:typo3-fluid-form-textarea@13.4)
-   [form.textfield](https://docs.typo3.org/permalink/t3viewhelper:typo3-fluid-form-textfield@13.4)
-   [form.upload](https://docs.typo3.org/permalink/t3viewhelper:typo3-fluid-form-upload@13.4)
-   [form.uploadDeleteCheckbox](https://docs.typo3.org/permalink/t3viewhelper:typo3-fluid-form-uploaddeletecheckbox@13.4)
-   [form.validationResults](https://docs.typo3.org/permalink/t3viewhelper:typo3-fluid-form-validationresults@13.4)
