4

I'm using Symfony 2.8 and I'm trying to create a registration form containing a "terms & conditions" check-box which isn't mapped to the underlying data model.

I've followed this cookbook article: How to Implement a Simple Registration Form

Everything in the form validation works, except for the the "terms & conditions" check-box. After submitting the form, the check-box validation doesn't get triggered.

This is my code:

namespace Likestripe\AdminBundle\Form\Type;


use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use FOS\UserBundle\Form\Type\RegistrationFormType as BaseType;
use Symfony\Component\Validator\Constraints\IsFalse;
use Symfony\Component\Validator\Constraints\IsTrue;


class RegistrationFormType extends AbstractType { //BaseType

/**
 * @param FormBuilderInterface $builder
 * @param array $options
 */
public function buildForm(FormBuilderInterface $builder, array $options) {
    // call parent constructor
    //parent::buildForm($builder, $options);

    // add your custom fields
    $builder->add('salutation', ChoiceType::class,   array('choices'  =>   array('Herr' => 0, 'Frau' => 1), 'choices_as_values' => true));
    $builder->add('firstname',  TextType::class,     array());
    $builder->add('lastname',   TextType::class,     array());
    $builder->remove('username');
    $builder->add('company',    new CompanyFormType());
    $builder->add('conditions', CheckboxType::class, array('mapped' => false, 'constraints' => new IsTrue(array("message" => "Bitte akzeptieren Sie noch die AGB und Nutzungsbedingungen."))));
    $builder->add('submit',     SubmitType::class,   array('label' => 'Registrieren'));
} // end function


public function getParent() {
    return 'FOS\UserBundle\Form\Type\RegistrationFormType';

    // Or for Symfony < 2.8
    // return 'fos_user_registration';
}

/**
 * function deprecated since 2.8 https://github.com/symfony/symfony/blob/2.8/UPGRADE-2.8.md#form
 *
 * @return string
 */
public function getName() {
    //return 'likestripe_user_registration';
    return $this->getBlockPrefix();
} // end function

public function getBlockPrefix() {
    return 'likestripe_user_registration';
}

} // end class

I can't see any difference between my code and the code demonstrated in the cookbook article.

Screen capture of my Symfony debug console: enter image description here

UPDATE:

As Kamil proposed, I've checked if the 'conditions' check-box form parameter gets posted after submitting the form.
The param gets posted als long as the check-box is checked, but if not, the "conditions" form parameter doesn't get posted at all... this behavior reminds me of this case.

I'm still wondering why the official Symfony documentation proposes a isTrue Validator which doesn't seem to be the solution to check for an unchecked check-box, any suggestions how to fix this?

Checkbox checked: enter image description here

Checkbox unchecked: enter image description here

Thanks in advance for your help
ninsky

Community
  • 1
  • 1
ninsky
  • 1,772
  • 23
  • 31

6 Answers6

2

If you let the 'required' of your CheckboxType to true, the constraints isTrue is not useful because the checkbox will always be true ! If change change that to :

$builder->add('conditions', CheckboxType::class, array('mapped' => false, 'required' => false, 'constraints' => new IsTrue(array("message" => "Bitte akzeptieren Sie noch die AGB und Nutzungsbedingungen."))));

With this configuration you can submit the form and if the box is not checked the constraints will send your message.

Hope this help ...

lemairep
  • 412
  • 2
  • 13
  • Hi lemairep, unfortunately this didn't help either. – ninsky Mar 29 '16 at 20:38
  • Sorry to ear that, looks like I didn't understand what was your problem exactly... – lemairep Mar 30 '16 at 01:55
  • If I can't resolve it by server side validation I will go for a JavaScript solution. But I didn't give up yet ;) – ninsky Mar 31 '16 at 07:24
  • Hi @ninsky, I'm not sure to understand what is your problem. I've try your code and it works for me : if you check the box you have conditions=1 if not you dont have conditions (that's the normal behavior for checkbox in html). The isTrue() just check if the box is checked or not at the validation time and trig your message if not. – lemairep Apr 01 '16 at 01:17
  • Hi lemairep, my problem is that IsTrue is never triggered. Doesn't matter if chechbox is checked or not. All other form fields are triggered... That's confusing – ninsky Apr 01 '16 at 04:58
  • I've just made a new test with a simple form (no fosuserbundle involved) and for me it's working as expected. If I don't check the box the validation process send the Error message. Could you check with a separate form without fosuserbundle ? – lemairep Apr 01 '16 at 05:35
  • I've also tested it with a non fosuserbundle related form (See one of my. comments). Which Symfony version do you use? I'm using 2.8.4 – ninsky Apr 01 '16 at 05:40
  • I use 3.0 but it looks like there is no difference with the 2.8 on this subject ... – lemairep Apr 01 '16 at 05:44
1

As a workaround, you can add a form listener to make sure you submit the value. Add following to the bottom of your buildForm() function:

     $builder->addEventListener(FormEvents::PRE_BIND, function (FormEvent $event) {
        $data = $event->getData();
        if (!isset($data['conditions'])) {
            $data['conditions'] = false;
        }
        $event->setData($data)
    });

As another workaround, you can perform a check in controller and show flash message if request headers do not contain 'conditions'.

Vasily802
  • 1,703
  • 2
  • 18
  • 35
  • Thanks. I'm trying to avoid logic within the controller as described in the symfony doc. But you're approach would work, yes. – ninsky Mar 31 '16 at 18:04
  • 2
    I edited my answer - please see above. This way you can check if 'conditions' been submitted right inside the buildForm() function. See, there are plenty workarounds, but perhaps you would like in the first place to find out why the validation is not working as described in the docs. I guess the only way to find it out is to take a look at your code beyond the snippet you provided. – Vasily802 Mar 31 '16 at 19:00
  • Thanks. But I'm still looking for the offical, slick solution as described in the Symfony documentation (link see my post) – ninsky Mar 31 '16 at 19:02
  • Monsieur, one upvote is better than a thousand "thank you" comments. – Vasily802 Apr 04 '16 at 17:47
  • 1
    Here we go @Vasily802 – ninsky Apr 04 '16 at 17:57
  • I've upgraded to Symfony 3.2 and FOSUserbundle 2.0 and the strange behaviour not validating the conditions checkbox still occured. By implementing a similar workaround like @Vasily802 proposed, I could solve the problem. Thanks – ninsky Apr 22 '17 at 17:48
1

Symfony docs mention it:

$builder
            ->add('email', EmailType::class);
            // ...
            ->add('termsAccepted', CheckboxType::class, array(
                'mapped' => false,
                'constraints' => new IsTrue(),
            ))
        );
numediaweb
  • 16,362
  • 12
  • 74
  • 110
0

Well, I don't see why is not working for you so in the meantime I give you an alternative way :)

$builder->add('conditions', CheckboxType::class , array('mapped' => false, 'required' => true, 'attr'=>array('onchange'=>"try{setCustomValidity('')}catch(e){}",'oninvalid'=>"setCustomValidity('Bitte akzeptieren Sie noch die AGB und Nutzungsbedingungen.')")));

Hope this work for you.

abdiel
  • 2,078
  • 16
  • 24
  • 1
    Not sure that embedding javascript in the builder code is the best idea ^^ – olaurendeau Mar 30 '16 at 20:41
  • That's the least of the problems, but do it them in twig if it makes you feel better {{ form_widget(form.conditions, { 'attr': {'onchange': "try{setCustomValidity('')}catch(e){}"} }) }} – abdiel Mar 30 '16 at 20:51
0

I've run your code with everything but the CompanyFormType line and it is working as expected.

enter image description here

enter image description here

Could you remove this CompanyFormType line and give it a try ?

olaurendeau
  • 659
  • 4
  • 12
  • I removed CompanyFormType but it didn't work either. I also added the conditions checkbox to a non FOSUserBundle related form to check if there's some kind of conflict with FOSUserBundle. But same effect - the checkbox doesn't get validated. That's really strange.... I'm using Symfony 2.8.4 (latest version) – ninsky Mar 31 '16 at 07:23
  • Could you add the twig view displaying the form and the controller code creating it ? – olaurendeau Mar 31 '16 at 12:19
0

You have to set the validation group Overriding Default FOSUserBundle Forms

By default, the Registration validation group is used when validating a new user registration. Unless you have overridden this value in the configuration, make sure you add the validation group named Registration to your name property.

How to do that you can find out here: Overriding Default FOSUserBundle Validation

vardius
  • 6,326
  • 8
  • 52
  • 97
  • Yes, I've set the validation group explicitly but didn't help. But it wouldn't make that much sense imho as I'm adding the IsTrue Validator within the formbuilder's add() function. – ninsky Mar 31 '16 at 18:07