Form.checkbox ViewHelper <f:form.checkbox>

ViewHelper which renders a simple checkbox <input type="checkbox">.

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

Single checkboxes

A single checkbox is usually mapped to a boolean property or controller argument.

However due to how checkboxes work in HTML a non-checked checkbox does not appear in the request sent by the form submission. Therefore properties and arguments need to default to false. They will then be set to true if the checkbox was checked.

While the value does not play a role when you are working with a checkbox, the argument must still be supplied.

Single optional checkbox tied to an action argument

Checkboxes in HTML work a little different from other input fields in that multiple or none at all can be checked.

Fluid outputs a normal HTML <input type="checkbox" ...> and some of the pitfalls also apply here. Especially a check box that is not sends no argument to the request.

packages/my_extension/Resources/Private/Templates/Comment/Newsletter.html
<f:form action="orderNewsletter" method="post">
    <div>
        <f:form.checkbox name="orderNewsletter" id="orderNewsletter" value="yes" />
        <label for="orderNewsletter">Order newsletter</label>
    </div>
    <div>
        <f:form.submit value="Submit" />
    </div>
</f:form>
Copied!

Then the controller action can then look like this:

packages/my_extension/Classes/Controller/NewsletterController.php
<?php

declare(strict_types=1);

namespace MyVendor\MyExtension\Controller;

use Psr\Http\Message\ResponseInterface;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;

class NewsletterController extends ActionController
{
    public function orderNewsletterAction(
        // If the checkbox is not checked, no argument is provided.
        // Default to false
        bool $orderNewsletter = false,
    ): ResponseInterface {
        if ($orderNewsletter) {
            // TODO: Newsletter ordering
        }
        return $this->htmlResponse();
    }
}
Copied!

The checkbox should already by checked / preselected

<f:form.checkbox name="accept" value="yes" checked="true" />
Copied!

You can also use a variable to determine whether the field should be checked:

<f:form.checkbox name="accept" value="yes" checked="{myVariable} == 5" />
Copied!

Property mapping - domain model property bound to single checkbox

If you are using the form with a model you can use the argument property to map the checkbox to a property of your domain model or data object:

packages/my_extension/Resources/Private/Templates/Newsletter/SomeForm.html
<f:form action="orderNewsletter" method="post" object="user" objectName="user">
    <div>
        <f:form.checkbox property="orderNewsletter" id="orderNewsletter" value="yes" />
        <label for="orderNewsletter">Order newsletter</label>
    </div>
    <div>
        <f:form.submit value="Submit" />
    </div>
</f:form>
Copied!

Then the controller action can look like this:

packages/my_extension/Classes/Controller/NewsletterController.php
<?php

declare(strict_types=1);

namespace MyVendor\MyExtension\Controller;

use MyVendor\MyExtension\Domain\Model\User;
use Psr\Http\Message\ResponseInterface;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;

class NewsletterController extends ActionController
{
    public function orderNewsletterAction(
        User $user,
    ): ResponseInterface {
        if ($user->isOrderNewsletter()) {
            // TODO: Newsletter ordering
        }
        return $this->htmlResponse();
    }
}
Copied!

An unchecked checkbox results in the property not being set. It should therefore default to false.

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

declare(strict_types=1);

namespace MyVendor\MyExtension\Domain\Model;

use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;

class User extends AbstractEntity
{
    protected bool $orderNewsletter = false;

    public function isOrderNewsletter(): bool
    {
        return $this->orderNewsletter;
    }

    public function setOrderNewsletter(bool $orderNewsletter): void
    {
        $this->orderNewsletter = $orderNewsletter;
    }

}
Copied!

If the property in the domain model is true when the form is displayed, the checkbox is preselected.

Multiple checkboxes for the same property

Unlike other input elements, multiple checkboxes can be used for the same property or action argument.

In this case they share the same name or property binding property but have distinct values.

If you are working with action arguments, multiple must be set.

Multiple checkboxes mapped to an array in a controller action

Multiple checkboxes are usually mapped to an array. It would however be possible, for example, to map them to an integer using binaries or such.

Therefore when working with multiple checkboxes and arrays, you have to tell Extbase how to map the data from the request to your controller action in an initialize action.

packages/my_extension/Resources/Private/Templates/Newsletter/SomeForm.html
<f:form action="orderNewsletter" method="post">
    <f:for each="{newsletterList}" as="newsletter" iteration="i">
        <div>
            <f:form.checkbox name="orderNewsletters" id="newsletter{i.cycle}" value="{newsletter.uid}" />
            <label for="newsletter{i.cycle}">{newsletter.title}</label>
        </div>
    </f:for>
    <div><f:form.submit value="Submit" /></div>
</f:form>
Copied!

Then the controller action can look like this:

packages/my_extension/Classes/Controller/NewsletterController.php
<?php

declare(strict_types=1);

namespace MyVendor\MyExtension\Controller;

use Psr\Http\Message\ResponseInterface;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
use TYPO3\CMS\Extbase\Property\TypeConverter\ArrayConverter;

class NewsletterController extends ActionController
{
    public function orderNewsletterAction(
        // This argument is mapped in initializeOrderNewsletterAction()
        array $orderNewsletters = [],
    ): ResponseInterface {
        if ($orderNewsletters !== []) {
            // TODO: Newsletter ordering
        }
        return $this->htmlResponse();
    }
    public function initializeOrderNewsletterAction()
    {
        if ($this->request->hasArgument('orderNewsletters')) {
            $this->arguments['orderNewsletters']
                ->getPropertyMappingConfiguration()
                ->setTypeConverterOption(
                    ArrayConverter::class,
                    ArrayConverter::CONFIGURATION_DELIMITER,
                    ',',
                );
        }
    }
}
Copied!

Property mapping of multiple checkboxes

When working with multiple checkboxes mapped to the property of an Extbase model or data object, the same property is used for all checkboxes to be mapped to that property.

Multiple checkboxes for multiple independent properties

When multiple checkboxes should be used independently they must have unique name properties to map to multiple action arguments or unique property values to bind to multiple properties.

Mandatory checkboxes - require a checkbox to be set

On the browser side you can use the HTML 5 "required" Attribute. As the <f:form.checkbox> ViewHelper allows arbitrary arguments, using the required property is possible even though it is not listed.

packages/my_extension/Resources/Private/Templates/Newsletter/SomeForm.html
<f:flashMessages/>
<f:form action="orderNewsletter" method="post" object="user" objectName="user">
    <div>
        <f:form.checkbox property="consentGiven" id="consentGiven" value="yes" required="required"/>
        <label for="consentGiven">I have accepted the terms and conditions</label>
    </div>
    <div>
        <f:form.submit value="Submit" />
    </div>
</f:form>
Copied!

Then the controller action can then look like this:

packages/my_extension/Classes/Controller/NewsletterController.php
<?php

declare(strict_types=1);

namespace MyVendor\MyExtension\Controller;

use MyVendor\MyExtension\Domain\Model\User;
use Psr\Http\Message\ResponseInterface;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;

class NewsletterController extends ActionController
{
    public function orderNewsletterAction(
        User $user,
    ): ResponseInterface {
        if ($user->isOrderNewsletter()) {
            // TODO: Newsletter ordering
        }
        return $this->htmlResponse();
    }
}
Copied!

You should also validate the model for the property to be true:

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

declare(strict_types=1);

namespace MyVendor\MyExtension\Domain\Model;

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

class User extends AbstractEntity
{
    #[Validate([
        'validator' => 'Boolean',
        'options' => ['is' => true],
    ])]
    protected bool $consentGiven = false;

    public function isConsentGiven(): bool
    {
        return $this->consentGiven;
    }

    public function setConsentGiven(bool $consentGiven): void
    {
        $this->consentGiven = $consentGiven;
    }
}
Copied!

If the server side validation on the model fails, the request is forwarded to the originating request with an error message.

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.

checked

checked
Type
bool
Specifies that the input element should be preselected

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

multiple

multiple
Type
bool
Default
false
Specifies whether this checkbox belongs to a multivalue (is part of a checkbox group)

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
string
Required
1
Value of input tag. Required for checkboxes