---
title: "Form.textfield ViewHelper <f:form.textfield>"
manual: "Fluid ViewHelper Reference"
version: "main"
permalink: "https://docs.typo3.org/permalink/t3viewhelper:typo3-fluid-form-textfield@main"
source: "Global/Form/Textfield.rst"
modified: "2026-09-16T13:37:51+00:00"
---

# Form.textfield ViewHelper `<f:form.textfield>`

ViewHelper which renders a text field `<input type="text">`.

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

> [!WARNING]
> User input, especially from free text fields, may contain harmful content.
> Sanitize all input data and prevent
> [Cross-site scripting (XSS)](https://docs.typo3.org/m/typo3/reference-coreapi/main/en-us/Security/TypesOfThreats/Index.html#security-xss).
>
> Also consider if [SQL injection](https://docs.typo3.org/m/typo3/reference-coreapi/main/en-us/Security/TypesOfThreats/Index.html#security-sql-injection)
> is possible.

## A basic text input bound to an action argument

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

**Fluid**

**packages/my_extension/Resources/Private/Templates/Search/SearchForm.fluid.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>

```

**Controller**

The [Extbase controller](https://docs.typo3.org/m/typo3/reference-coreapi/main/en-us/ExtensionArchitecture/Extbase/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();
  }
}

```

## A text input bound to a model property

Using the [property](https://docs.typo3.org/permalink/t3viewhelper:viewhelper-argument-typo3-cms-fluid-viewhelpers-form-textfieldviewhelper-property@main)
argument, a text field can be bound to the property of an
[Extbase model](https://docs.typo3.org/m/typo3/reference-coreapi/main/en-us/ExtensionArchitecture/Extbase/Domain/Model.html#extbase-model).

For this, the surrounding form must also define the
[object](https://docs.typo3.org/permalink/t3viewhelper:viewhelper-argument-typo3-cms-fluid-viewhelpers-formviewhelper-object@main)
property.

**packages/my_extension/Resources/Private/Templates/Blog/Comment.fluid.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>

```

## Validation of plain text input fields

User input often requires validation. For text fields, some common cases include:

-   The name should not be empty
-   The email address must be a valid email address and it is required.
-   The link to the user's homepage must be a valid URL if it is entered at all.

### Using arbitrary arguments

As the Form.textfield ViewHelper allows arbitrary arguments, you can use any
additional argument that you would also use on an HTML input element, including
HTML 5 arguments like [required](https://www.w3schools.com/tags/att_input_required.asp)
and [autocomplete](https://www.w3schools.com/tags/att_input_autocomplete.asp).

### ARIA arguments for improved accessibility

You have the choice of defining each [aria-\*](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA)
attribute separately as you would do in HTML, or by passing them as an array to
the Fluid argument [aria](https://docs.typo3.org/permalink/t3viewhelper:viewhelper-argument-typo3-cms-fluid-viewhelpers-form-textfieldviewhelper-aria@main).

### Data arguments for JavaScript validation etc

Same goes with [data-\*](https://www.w3schools.com/tags/att_data-.asp) attributes.
They can also be set with the Fluid argument
[data](https://docs.typo3.org/permalink/t3viewhelper:viewhelper-argument-typo3-cms-fluid-viewhelpers-form-textfieldviewhelper-data@main)
as an array. `data-*` attributes are commonly used with JavaScript libraries
for frontend validation like [Parsley](https://parsleyjs.org/).

### Server side validation

> [!WARNING]
> Never rely on frontend validation alone! It might not work in all browsers.

Always use [Validation for Extbase models and controllers](https://docs.typo3.org/m/typo3/reference-coreapi/main/en-us/ExtensionArchitecture/Extbase/Validation/Index.html#extbase-validation)
or validate the input on server-side manually.

### Example with validation and aria-attributes

**Fluid**

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

```html
<f:form action="create" controller="Comment"
        objectName="comment" object="{newComment}" method="post">

    <label for="name">Name:</label>
    <f:form.textfield property="name" id="name"
                      autocomplete="name" required="required"
                      aria-required="true" />

    <label for="email">E-Mail (*):</label>
    <f:form.textfield property="email" id="email" type="email"
                      autocomplete="email" required="required"
                      aria="{required: 'true', describedby: 'email-hint'}" />

    <label for="homepage">Website:</label>
    <f:form.textfield property="homepage" id="homepage" type="url"
                      autocomplete="url" />

    <f:form.submit value="Send" />
</f:form>

<span id="email-hint">
  (*) We will never share your email.
</span>

```

**Controller**

The [Extbase controller](https://docs.typo3.org/m/typo3/reference-coreapi/main/en-us/ExtensionArchitecture/Extbase/Controller/Index.html#extbase-controller)
action `commentFormAction()` uses the [IgnoreValidation](https://docs.typo3.org/m/typo3/reference-coreapi/main/en-us/ExtensionArchitecture/Extbase/Appendix/Attributes.html#extbase-annotation-ignore-validation)
argument to disable the validation. Whenever the validation fails in the
`createAction()` the request will be forwarded back to this action. The
model still contains the non-valid data so that the user can edit it.

**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');
  }
}

```

**Model**

The [Extbase model](https://docs.typo3.org/m/typo3/reference-coreapi/main/en-us/ExtensionArchitecture/Extbase/Domain/Model.html#extbase-model)
uses [built-in validators](https://docs.typo3.org/m/typo3/reference-coreapi/main/en-us/ExtensionArchitecture/Extbase/Validation/Index.html#extbase-validation):

**packages/my_extension/Classes/Domain/Model/Comment.php**

```php
<?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' => 'NotEmpty'])]
  protected string $name = '';

  #[Validate(['validator' => 'NotEmpty'])]
  #[Validate(['validator' => 'EmailAddress'])]
  protected string $email = '';

  #[Validate(['validator' => 'Url'])]
  protected string $homepage = '';
}

```

## Arguments

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

-   **additionalAttributes**

    -   *Type:* array

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

-   **aria**

    -   *Type:* array

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

-   **data**

    -   *Type:* array

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

-   **errorClass**

    -   *Type:* string
    -   *Default:* 'f3-form-error'

    CSS class to set if there are errors for this ViewHelper

-   **name**

    -   *Type:* string

    Name of input tag

-   **property**

    -   *Type:* string

    Name of Object Property. If used in conjunction with \<f:form object="...">, the "name" property will be ignored, while "value" can be used to specify a default field value instead of the object property value.

-   **required**

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

    If the field is required or not

-   **type**

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

    The field type, e.g. "text", "email", "url" etc.

-   **value**

    -   *Type:* mixed

    Value of input tag
