VMC
VMC

Reputation: 1388

What is the right approach to validate multiple checkboxes at once in Symfony2 (one required)?

Let's say we have a Symfony2 form containing 3 checkboxes (A, B, C) and we want the user to tick at least one checkbox in order to validate the form, so any combination ([A], [B], [C], [A,B], [A,C], [B,C] ,[A,B,C]) would return true and no selection [] returns false.

What is the right approach to achieve this using Symfony validators on Doctrine objects?

Edit:
Each checkbox is mapped to it's own column in the database using Doctrine @ORM\Column(type="boolean")

Upvotes: 1

Views: 1956

Answers (4)

Michael Käfer
Michael Käfer

Reputation: 1796

We can use the Expression constraint:

namespace App\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints as Assert;

class MyType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('myFirstCheckbox', CheckboxType::class, [
                'required'=> false,
            ])
            ->add('mySecondCheckbox', CheckboxType::class, [
                'required'=> false,
            ])
        ;
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            'constraints' => new Assert\Expression(
                expression: 'this.get("myFirstCheckbox").getData() or this.get("mySecondCheckbox").getData()',
                message: 'Please choose 1 of the 2 checkboxes.',
            )
        ]);
    }
}

Upvotes: 0

VMC
VMC

Reputation: 1388

Problem solved.

Based on Symfony2 Class Constraint Validator documentation and on Added info on changes to setting validation subpath to UPGRADE-2.1.md

In my entity class I've added:

class Message
{

  // ...

  // check if user selected at least one network to publish the message
  public function isNetworkSelected(ExecutionContext $context)
  {
    if (!$this->network_twitter && !$this->network_facebook && !$this->network_googleplus)
    {
      $context->addViolationAtSubPath('network_facebook', 'Please select at least one network', array(), null);
    }
  }

  // ...

}

In validation.yml:

MY\MessageBundle\Entity\Message
    constraints:
        - Callback:
            methods:   [isNetworkSelected]

Upvotes: 1

noetix
noetix

Reputation: 4923

If you're correctly using the choice field type for your list of options, you can use ChoiceValidator:

@Assert\Choice(min=1, minMessage = "You must choose at least one option.")

From the docs:

If the multiple option is true, then you can use the min option to force at least XX number of values to be selected. For example, if min is 3, but the input array only contains 2 valid items, the validation will fail.

Upvotes: 3

sjramsay
sjramsay

Reputation: 555

Do you have a button control? If so, on the click event, check if there is a selection made if so, return true, else return false.

Upvotes: 0

Related Questions