Form.password ViewHelper <f:form.password>

ViewHelper which renders a simple password text box <input type="password">.

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

A basic password field

The basic usage sets a name and renders a password input:

Resources/Private/Templates/User/LoginForm.html
<f:form action="login" controller="User" method="post">
    <label for="password">Password:</label>
    <f:form.password name="myPassword" id="password" />
    <f:form.submit value="Login" />
</f:form>
Copied!
<input type="password" name="myPassword" value="" />
Copied!

Binding to a model property

You can bind the password field to a property in an Extbase model. This requires the form to define the object and objectName as well.

Resources/Private/Templates/User/RegisterForm.html
<f:form action="register" controller="User" method="post"
        objectName="user" object="{newUser}">

    <label for="username">Username:</label>
    <f:form.textfield property="username" id="username" />

    <label for="password">Password:</label>
    <f:form.password property="password"
                     id="password"
                     aria="{required: 'true'}"
                     autocomplete="new-password" />

    <f:form.submit value="Register" />
</f:form>
Copied!

Excursion: Validation and hashing of password fields

A password should be validated against the Password policy and must always be hashed before saving. Never save a plain text password to the database.

Classes/Domain/Model/User.php
<?php

declare(strict_types=1);

namespace MyVendor\MyExtension\Domain\Model;

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

class User extends AbstractEntity
{
    #[Validate(['validator' => 'NotEmpty'])]
    public string $username = '';

    // Never save a plaintext password to the database. Make it transient to
    // prevent saving
    #[Transient]
    #[Validate(['validator' => 'NotEmpty'])]
    #[Validate(['validator' => 'StringLength', 'options' => ['minimum' => 8]])]
    public string $plainTextPassword = '';

    // Saved the hashed password to the database
    public string $password = '';
}
Copied!
Classes/Controller/UserController.php
<?php

declare(strict_types=1);

namespace MyVendor\MyExtension\Controller;

use MyVendor\MyExtension\Domain\Model\User;
use Psr\Http\Message\ResponseInterface;
use TYPO3\CMS\Core\Crypto\PasswordHashing\PasswordHashFactory;
use TYPO3\CMS\Core\PasswordPolicy\PasswordPolicyAction;
use TYPO3\CMS\Core\PasswordPolicy\PasswordPolicyValidator;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;

class UserController extends ActionController
{
    public function __construct(
        private readonly PasswordHashFactory $passwordHashFactory,
        private readonly UserRepository $userRepository,
    ) {}

    public function registerFormAction(?User $user = null): ResponseInterface
    {
        $this->view->assign('newUser', $user ?? new User());
        return $this->htmlResponse();
    }

    public function registerAction(User $user): ResponseInterface
    {
        $passwordValidator = new PasswordPolicyValidator(
            PasswordPolicyAction::NEW_USER_PASSWORD,
        );
        // validate password against password policy
        if (!$passwordValidator->isValidPassword($user->plainTextPassword)) {
            foreach ($passwordValidator->getValidationErrors() as $error) {
                $this->addFlashMessage('Password is not correct: ' . $error);
            }
            // Unset the plain text password before returning it to the view
            $user->plainTextPassword = '';
            return $this->redirect('registerForm', null, null, ['user' => $user]);
        }

        // Hash password using the default hash instance for the Frontend
        // NEVER save a plain text password to the database!
        $user->password = $this->passwordHashFactory
            ->getDefaultHashInstance('FE')
            ->getHashedPassword($user->plainTextPassword);
        $this->userRepository->update($user);

        $this->addFlashMessage('Password was saved.');
        return $this->redirect('registerForm');
    }
}
Copied!

The example above shows validation inlined in an action of the controller for brevity. For re-usability and better architecture following best practices, you can create a custom validator for this: Custom Extbase validator implementation.

ARIA and data attributes

You can pass aria-* and data-* attributes as arrays to the aria and data arguments for accessibility and JavaScript validation support.

<f:form.password property="password"
                 aria="{required: 'true'}"
                 data="{toggle: 'password'}" />
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.

value

value
Type
mixed
Value of input tag