Skip to content
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

ChoiceType returns wrong data on submit if clearMissing is false #16802

Closed
ossinkine opened this issue Dec 2, 2015 · 30 comments
Closed

ChoiceType returns wrong data on submit if clearMissing is false #16802

ossinkine opened this issue Dec 2, 2015 · 30 comments

Comments

@ossinkine
Copy link
Contributor

ossinkine commented Dec 2, 2015

I've created TestFormType

class TestType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('text', 'text')
            ->add('choice', 'choice', ['choices' => ['FOO' => 'foo', 'BAR' => 'bar'], 'expanded' => true])
        ;
    }

    public function getName()
    {
        return 'test';
    }
}

created the form and trying to submit data

$data = [
    'text'   => 'foo',
    'choice' => 'foo',
];
$form = $this->createForm('test', $data);
$form->submit(
    [
        'text'   => 'bar',
        'choice' => 'bar',
    ],
    false
);

and now $form->getData() will return an array:

array (size=2)
    'text' => string 'bar' (length=3)
    'choice' => string 'foo' (length=3)

I expect to receive bar for both fields.

I'm working on the latest version of 4.4 branch
See the reproducer for this issue https://github.com/ossinkine/symfony-issue-16802

@stof
Copy link
Member

stof commented Dec 2, 2015

@webmozart can you take a look ?

@1ed
Copy link
Contributor

1ed commented Dec 2, 2015

@ossinkine the choices option actually looks like this [0 => 'foo', 1 => 'bar'] and by default the keys used as values in the HTML select element so the submitted value should be 1 to select the bar option, shouldn't it? See http://symfony.com/doc/2.7/reference/forms/types/choice.html#example-usage

@ossinkine
Copy link
Contributor Author

@1ed My bad.
I fixed choices option in the form. Also, I added expanded option. The issue is reproduced.
I made changes in the first comment and in my fork.

@geoffrey-brier
Copy link
Contributor

@stof @webmozart Just upgraded in 2.8 and I'm facing the same issue. Seems like it comes from the expanded option being set to true, it's as if the data wasn't properly cleaned in the ChoiceType class.

The following code fixes the problem, but I'm really not sure if that's the way to fix it.

<?php
// Symfony\Component\Form\Extension\Core\Type\ChoiceType.php
    foreach ($form as $child) {
        $value = $child->getConfig()->getOption('value');

        // Add the value to $data with the child's name as key
        if (isset($valueMap[$value])) {
            $data[$child->getName()] = $value;
            unset($unknownValues[$value]);
            continue;
        }
        // Doing this fixes the problem
        $data[$child->getName()] = false;
    }

@HeahDude
Copy link
Contributor

Hi @ossinkine, I can confirm your issue, a workaround it to call the field data :

$form->get('choice')->getData()
// will get the expected
string 'bar' (length=3)

It's a problem of propagation of submitted data.

I'll send a PR as a proposal to fix this issue, thanks for reporting it.

Status: reviewed

@HeahDude
Copy link
Contributor

Hi @ossinkine, could you please try the fix provided in #17771 to see if it works for your issue ?

@ossinkine
Copy link
Contributor Author

Hi @HeahDude
It seems to be working for me

@HeahDude
Copy link
Contributor

Thanks for the feedback.

@ureimers
Copy link
Contributor

ureimers commented May 9, 2017

So as #17771 is closed without a pull (for good reasons, I suppose) this problem still exists in all current Symfony versions.

@xabbuh
Copy link
Member

xabbuh commented Nov 13, 2018

This seems to have been fixed in the meantime as I can no longer reproduce.

@xabbuh xabbuh closed this as completed Nov 13, 2018
@ossinkine
Copy link
Contributor Author

The issue is still reproduced.
There is the reproducer for Symfony 4.2 https://github.com/ossinkine/symfony-issue-16802

@xabbuh xabbuh reopened this Feb 7, 2019
@ostrolucky
Copy link
Contributor

you might want link this url to one remaining linked issue that is still open

@alexander-schranz
Copy link
Contributor

alexander-schranz commented Mar 10, 2020

I did fall into this issue.

So currently the ChoiceType is given clearMissing = false here:

$child->submit($isSubmitted ? $submittedData[$name] : null, $clearMissing);

Maybe we should introduce a new form configuration e.g.:clear_missing which can be true|false|null where null means = inherit from parent. And the ChoiceType default value is false true.

@xabbuh @HeahDude what do you think?

@xabbuh
Copy link
Member

xabbuh commented Mar 10, 2020

Would #35938 help here?

@alexander-schranz
Copy link
Contributor

@xabbuh did test it but sadly that does not solve this issue.

@alexander-schranz
Copy link
Contributor

alexander-schranz commented Mar 10, 2020

@xabbuh oh you asked if it helps. Basically we could go on that flag and do:

if ($child->getConfig()->getAttribute('_false_is_empty')) {
    $clearMissing = true;
}

$child->submit($isSubmitted ? $submittedData[$name] : null, $clearMissing);

at

$child->submit($isSubmitted ? $submittedData[$name] : null, $clearMissing);

and then the entity looks good for me.

But not sure if its a good idea to go on that flag and how it will be solved in Symfony 5.1. /cc @fancyweb @HeahDude

@bluser86
Copy link

bluser86 commented Sep 1, 2020

We have run into this issue today as well on symfony 5.1.3. We found that a form eventlistener helped us work around the issue:

<?php

namespace App\Form\EventSubscriber;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\Event\PreSubmitEvent;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;

class ChoiceSubscriber implements EventSubscriberInterface
{
    /**
     * {@inheritdoc}
     */
    public static function getSubscribedEvents()
    {
        return [
            FormEvents::PRE_SUBMIT => 'onPreSubmit',
        ];
    }

    /**
     * @param PreSubmitEvent $event
     * @throws \Symfony\Component\Form\Exception\OutOfBoundsException
     * @throws \Symfony\Component\Form\Exception\RuntimeException
     * @throws \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function onPreSubmit(PreSubmitEvent $event)
    {
        $form = $event->getForm();
        $data = $event->getData();

        if (isset($data['choice']) && $data['choice'] !== $form->get('choice')->getData()) {
            $form->get('choice')->setData(null);
        }
    }
}

The work around constitutes checking during the pre submit event if the submitted data has changed compared to the pre-populated form data. If this is the case reset the current form data to null. Hopefully this helps others who might run into this problem in the future until a patch is made to fix it.

@carsonbot
Copy link

Hey, thanks for your report!
There has not been a lot of activity here for a while. Is this bug still relevant? Have you managed to find a workaround?

@ostrolucky
Copy link
Contributor

.

@carsonbot carsonbot removed the Stalled label Mar 2, 2021
@xabbuh
Copy link
Member

xabbuh commented Mar 6, 2021

I am not sure I understand the issue. Submitting invalid values to a choice type means that a TransformationFailedException is being thrown and thus the data is not going to get mapped back to the underlying object. This is expected.

@ostrolucky
Copy link
Contributor

Indeed, I think this can be closed after all. Problem in post of OP was that he is submitting choice key instead of value.

@ossinkine
Copy link
Contributor Author

I'll update my reproducer to the latest Symfony 4.4 and try to reproduce.

@ossinkine
Copy link
Contributor Author

I've updated Symfony in my reproducer to the latest 4.4 version and the issue is still reproducer.
@xabbuh @ostrolucky Why do you guys think I submit invalid values to choice? I submit foo value which is one of choices. If you look at first post and see choice values as keys, such behavior was in Symfony 2.7 (this was the most actual version when issue created). In the fresh reproducer the values set up correctly, please review https://github.com/ossinkine/symfony-issue-16802

@ostrolucky
Copy link
Contributor

No, FOO and BAR are valid choices. Choice keys were used by default in Symfony 2.x, but it was deprecated since 2.8 and values were made default since 3.0 https://symfony.com/doc/2.8/reference/forms/types/choice.html#choices-as-values

@ossinkine
Copy link
Contributor Author

@ostrolucky please look at reproducer https://github.com/ossinkine/symfony-issue-16802/blob/771f6579ad4ba7c27b1d9bf44d4db0c8092588c2/src/Form/TestType.php#L17

        $builder
            ->add('text', TextType::class)
            ->add('choice', ChoiceType::class, ['choices' => ['FOO' => 'foo', 'BAR' => 'bar'], 'expanded' => true])
        ;

choices are values, so foo and bar are valid

@xabbuh
Copy link
Member

xabbuh commented Mar 7, 2021

Thanks, I can now reproduce it.

Status: Reviewed

@ostrolucky
Copy link
Contributor

Could you please also update original post?

@ossinkine
Copy link
Contributor Author

@ostrolucky updated

@xabbuh
Copy link
Member

xabbuh commented Mar 8, 2021

Can you try out #40417 please?

@fabpot fabpot closed this as completed Mar 9, 2021
fabpot added a commit that referenced this issue Mar 9, 2021
…ssing is set to false (xabbuh)

This PR was merged into the 4.4 branch.

Discussion
----------

[Form] clear unchecked choice radio boxes even if clear missing is set to false

| Q             | A
| ------------- | ---
| Branch?       | 4.4
| Bug fix?      | yes
| New feature?  | no
| Deprecations? | no
| Tickets       | Fix #16802
| License       | MIT
| Doc PR        |

Commits
-------

e7b4851 clear unchecked choice radio boxes even if clear missing is set to false
@ossinkine
Copy link
Contributor Author

Thank you @xabbuh, your fix fixes the issue for me

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

No branches or pull requests