chris
chris

Reputation: 2243

Remove submitted value from form if form validation fails

With the following (shortened) form I register new users in TYPO3 v12:

<f:form action="register" name="registration" object="{registration}" id="register-form">

    <f:form.textfield
        property="login"
        id="login" />

    <f:form.textfield
        type="password"
        property="password"
        id="password" />

</f:form>

The validation happens in the model:

class Registration extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity
{
    /**
     * @var string
     * @Extbase\Validate("NotEmpty")
     * @Extbase\Validate("StringLength", options={"minimum": 8, "maximum": 30})
     */
    protected string $login = '';

    /**
     * @var string
     * @Extbase\Validate("NotEmpty")
     * @Extbase\Validate("RegularExpression", options={"regularExpression": "/^.*(?=.{8,})(?=.*[a-zA-Z])(?=.*\d).*$/"})
     */
    protected string $password = '';
}

Submitting the form with less the eight characters for the login or password will show the form again. The form fields will show the submmited data and the error messages accordingly. This is the normal behaviour.

Now I don't want to return the password to the form after it was submitted, the field shall be emptied.

I did the following with no luck:

Upvotes: 0

Views: 52

Answers (2)

chris
chris

Reputation: 2243

In order to use the normal model validation, you can use a custom viewhelper, which does not show the submitted value for the form field:

Viewhelper:

<?php

declare(strict_types=1);

namespace Vendor\Extension\ViewHelpers;

use TYPO3\CMS\Fluid\ViewHelpers\Form\AbstractFormFieldViewHelper;

/*
 * This is a modified version of `TYPO3\CMS\Fluid\ViewHelpers\Form\TextfieldViewHelper`
 * It removes the value from the password field.
 *
 * Modifications are marked below.
 */
class PasswordViewHelper extends AbstractFormFieldViewHelper
{
    /**
     * @var string
     */
    protected $tagName = 'input';

    public function initializeArguments(): void
    {
        parent::initializeArguments();
        $this->registerTagAttribute('autofocus', 'string', 'Specifies that an input should automatically get focus when the page loads');
        $this->registerTagAttribute('disabled', 'string', 'Specifies that the input element should be disabled when the page loads');
        $this->registerTagAttribute('maxlength', 'int', 'The maxlength attribute of the input field (will not be validated)');
        $this->registerTagAttribute('readonly', 'string', 'The readonly attribute of the input field');
        $this->registerTagAttribute('size', 'int', 'The size of the input field');
        $this->registerTagAttribute('placeholder', 'string', 'The placeholder of the textfield');
        $this->registerTagAttribute('pattern', 'string', 'HTML5 validation pattern');
        $this->registerArgument('errorClass', 'string', 'CSS class to set if there are errors for this ViewHelper', false, 'f3-form-error');
        $this->registerUniversalTagAttributes();
        $this->registerArgument('required', 'bool', 'If the field is required or not', false, false);
        $this->registerArgument('type', 'string', 'The field type, e.g. "text", "email", "url" etc.', false, 'text');
    }

    public function render(): string
    {
        $required = $this->arguments['required'];
        $type = $this->arguments['type'];

        $name = $this->getName();
        $this->registerFieldNameForFormTokenGeneration($name);
        $this->setRespectSubmittedDataValue(true);

        $this->tag->addAttribute('type', $type);
        $this->tag->addAttribute('name', $name);

        $value = $this->getValueAttribute();

        // Original of `TextfieldViewHelper`
        /*
        if ($value !== null) {
            $this->tag->addAttribute('value', $value);
        }
        */

        // Modification start
        $this->tag->addAttribute('value', '');
        // Modification end

        if ($required !== false) {
            $this->tag->addAttribute('required', 'required');
        }

        $this->addAdditionalIdentityPropertiesIfNeeded();
        $this->setErrorClassAttribute();

        // Modification start
        if ($value !== null) {
            if ($this->hasArgument('class')) {
                $cssClass = $this->arguments['class'] . ' ';
            } else {
                $cssClass = '';
            }
            $cssClass .= 'f3-form-error';
            $this->tag->addAttribute('class', $cssClass);
        }
        // Modification end

        return $this->tag->render();
    }
}

No you can use this viewhelper in the view:

<vendor:password
    type="password"
    property="password"
    id="password"
    class="form-control" />

Upvotes: 0

Mogens
Mogens

Reputation: 1181

Passing the password as name should do the job:

<f:form.textfield
    type="password"
    name="password"
    id="password" />

EDIT:
You can use:

<f:debug>{_all}</f:debug>

to see all variables. There should be an error, when the validation fails. You can use this variable, to implement an if condition, to set the class of your textfield.

Upvotes: 0

Related Questions