10000 Cannot uncheck checkbox field mapped to the entity · Issue #20179 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

Cannot uncheck checkbox field mapped to the entity #20179

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
ttibensky opened this issue Oct 7, 2016 · 11 comments · May be fixed by #45081
Closed

Cannot uncheck checkbox field mapped to the entity #20179

ttibensky opened this issue Oct 7, 2016 · 11 comments · May be fixed by #45081

Comments

@ttibensky
Copy link

I'm having issues submitting a form which contains checkbox field. When the mapped field in the entity is true, checkbox is checked and I want to uncheck it and submit the form it won't pass through form validation. I found some issues mentioned this and Im aware of if checkbox is unchecked, its value isn't present in the POST request, so it should be interpreted as null. I have other checkboxes in other forms on my site, but all of the others works. So I was thinking and realized that the form witch doesn't work contains only the checkbox field and nothing else:

<?php

namespace SomeCompany\SomeBundle\Form\Type\Person\Author;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class AlertWhenWrittenType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('checkbox', CheckboxType::class, [
            'required' => false,
        ]);
    }

    /**
     * @param OptionsResolver $resolver
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(['csrf_protection' => false]);
    }
}

So I tried to add another field (hidden, not mapped and with empty_data set to true) just to see what happens:

<?php

namespace SomeCompany\SomeBundle\Form\Type\Person\Author;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class AlertWhenWrittenType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('checkbox', CheckboxType::class, [
            'required' => false,
        ]);

        // if there is only a checkbox field in the form,
        // it can't be unchecked, if you uncheck it and submit the form
        // form validation won't pass
        // magically, if I add any another field,
        // you will be able to uncheck the checkbox and validation will pass
        // this is needed until it is fixed in symfony core
        $builder->add('uglyHack', HiddenType::class, [
            'required' => false,
            'mapped' => false,
            'empty_data' => true,
        ]);
    }

    /**
     * @param OptionsResolver $resolver
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(['csrf_protection' => false]);
    }
}

also needed to add that field to my twig template

{{ form_widget(form.checkbox) }}
{{ form_widget(form.uglyHack) }}

and now, miraculously, Im able to uncheck the checkbox and submit the form. Validation now passes and entity field value is now set to false.
I think that its happening because there is only the checkbox field in the form. If checkbox is not checked, its value is not send through POST, but there are no other fields so $_POST is empty
and I think that might cause the problem to appear. Maybe empty $_POST is handled wrong?

I'm using symfony 3.0.9

@xabbuh xabbuh added the Form label Oct 7, 2016
@xabbuh
Copy link
Member
xabbuh commented Oct 7, 2016

The issue is that the Form component is not able to detect that the form was submitted as none of the fields is present (at least when using handleRequest()). Though you can workaround that by always calling submit() when the request is a POST request.

@ostrolucky
Copy link
Contributor
ostrolucky commented Oct 7, 2016

This reminds me of #17899

Maybe Symfony forms could set initial state for all the checkboxes (in case of POST) as boolean false and then continue to work with checkboxes internally as booleans, instead of expecting strict nulls. Both problems would be solved.

@ttibensky
Copy link
Author

@gadelat but thats not how html checkbox works. I agree with what you said but it would need to become a BooleanType. Because CheckboxType is working exactly like designed = exactly like it should work.

@ostrolucky
Copy link
Contributor

@ttibensky I'm aware that this mess is caused by how forms in web browsers were designed (wrong IMO), but it needs to be dealt with somehow.

@backbone87
Copy link
Contributor

in Contao this issue is solved by including a hidden input in front of the checkbox input with the same name as the checkbox, this way if the checkbox is unchecked the POST data looks like CHECKBOX_NAME= and if its checked CHECKBOX_NAME=&CHECKBOX_NAME=CHECKBOX_VALUE and because how PHP parses POST data the empty value gets overridden with CHECKBOX_VALUE in the latter case.

@xabbuh
Copy link
Member
xabbuh commented Oct 12, 2016

see #20210 for a PR

@ttibensky
Copy link
Author

@xabbuh looks good, this solves the issue perfectly. Feel free to close this ticket after it is merged.

@HeahDude
Copy link
Contributor
HeahDude commented Dec 3, 2016

@ttibensky Could you please confirm that #17771 is fixing your issue as well? Thanks!

@ttibensky
Copy link
Author

@HeahDude I'm not using PATCH method, but yeah, it does the thing. For me this ticket is done.

@HeahDude
Copy link
Contributor
HeahDude commented Dec 9, 2016

Thank you @ttibensky for confirming this :)

@xabbuh xabbuh closed this as completed Sep 13, 2018
@xabbuh
Copy link
Member
xabbuh commented Sep 30, 2018

I just noticed that I closed here accidentally without noticing that #17771 was never merged. However, we can still keep it closed as we also have #14938 which (basically) covers the same issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants
0