Form.textfield ViewHelper <f:form.textfield>

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

Go to the source code of this ViewHelper: Form\TextfieldViewHelper.php (GitHub).

A basic text input bound to an action argument

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

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

The Extbase controller action could for example look like this:

packages/my_extension/Classes/Controller/SearchController.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();
    }
}
Copied!

A text input bound to a model property

Using the property argument, a text field can be bound to the property of an Extbase model.

For this, the surrounding form must also define the object property.

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

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 and autocomplete.

ARIA arguments for improved accessibility

You have the choice of defining each aria-* attribute separately as you would do in HTML, or by passing them as an array to the Fluid argument aria.

Data arguments for JavaScript validation etc

Same goes with data-* attributes. They can also be set with the Fluid argument data as an array. data-* attributes are commonly used with JavaScript libraries for frontend validation like Parsley.

Server side validation

Always use Validation for Extbase models and controllers or validate the input on server-side manually.

Example with validation and aria-attributes

packages/my_extension/Resources/Private/Templates/Comment/CommentForm.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>
Copied!

The Extbase controller action commentFormAction() uses the IgnoreValidation 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

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

The Extbase model uses built-in validators:

packages/my_extension/Classes/Domain/Model/Comment.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 = '';
}
Copied!

Arguments

additionalAttributes

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

aria

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

data

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

errorClass

errorClass
Type
string
Default
'f3-form-error'
CSS class to set if there are errors for this ViewHelper

name

name
Type
string
Name of input tag

property

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

required
Type
bool
Default
false
If the field is required or not

type

type
Type
string
Default
'text'
The field type, e.g. "text", "email", "url" etc.

value

value
Type
mixed
Value of input tag