8000 Choice type expanded with boolean choices with choices_as_values always preselects `false` value · Issue #17718 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

Choice type expanded with boolean choices with choices_as_values always preselects false value #17718

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
webdevilopers opened this issue Feb 7, 2016 · 6 comments

Comments

@webdevilopers
Copy link

I've updated to 2.7 and changed my choice types to use choices_as_values.
Most of my choices are simple "No" or "Yes". But they must not be preselected - the user is forced to choose. That is why none of my radio buttons is initially checked.

I tried this with 2.7:

$builder->add('aberdeenBlind', 'choice', array(
                'choices' => array(
                    'Ja' => true,
                    'Nein' => false
                ),
                'choices_as_values' => true,
                'expanded' => true,
                'required' => true
            ))

Unfortunately the second radio button (false => 'Nein') is preselected. This also happens when flipping the order of the choices. The false choice is always preselected.

I played around with other options e.g. placeholder, empty_* etc. but then I recognized:
This only seems to happen when using boolean values. The following example would not preselect any value:

$builder->add('aberdeenBlind', 'choice', array(
                'choices' => array(
                    'Ja' => 'Y', // or '1'
                    'Nein' => 'N' // or '0'
                ),
                'choices_as_values' => true,
                'expanded' => true,
                'required' => true
            ))

Possibly related:

@raziel057
Copy link
Contributor

This is the same problem as #17677

@webdevilopers
Copy link
Author

You are right @raziel057 . I browsed the issues before posting but didn't look for e.g. placeholder.
Should we keep both issues open @javiereguiluz ?

@javiereguiluz
Copy link
Member

If it's the same bug, we usually close the new one in favor of the old one (unless the new one provides more info or engages a better discussion).

@webdevilopers
Copy link
Author

I think it is important to note that the issue is not linked to the placeholder option.
It looks like it is caused by a boolean choice false itself. The value for the choice is an empty string.
Since no data has been populated for the form the field type thinks the values match and pre-selects the radio button.

I will add a dump too for my example above:
boolean_issue_choicetype

@raziel057
Copy link
Contributor

In fact the string cast for false is the empty value which conflicts with the empty value of the placeholder.

To avoid this issue, I made a custom BooleanType:

namespace PTC\CoreBundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;

use PTC\CoreBundle\Form\DataTransformer\StringToBooleanTransformer;

class PtcBooleanType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->addModelTransformer(new StringToBooleanTransformer('1', '0'));
    }

    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'choices' => array(
                'yes' => '1',
                'no' => '0',
            ),
        ));

        $resolver->addAllowedValues('multiple', false);
    }

    /**
     * {@inheritdoc}
     */
    public function getParent()
    {
        return ChoiceType::class;
    }
}

With a String to Boolean Transformer:

<?php
namespace PTC\CoreBundle\Form\DataTransformer;

use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;

class StringToBooleanTransformer implements DataTransformerInterface
{
    /**
     * @var string
     */
    private $trueValue;

    /**
     * @var string
     */
    private $falseValue;

    /**
     * @param string $trueValue
     * @param string $falseValue
     */
    public function __construct($trueValue, $falseValue)
    {
        $this->trueValue = $trueValue;
        $this->falseValue = $falseValue;
    }

    /**
     * {@inheritDoc}
     */
    public function transform($value)
    {
        if (null === $value) {
             return null;
        }

        if (!is_bool($value)) {
            throw new TransformationFailedException('Expected a Boolean.');
        }

        return true === $value ? $this->trueValue : $this->falseValue;
    }

    /**
     * {@inheritDoc}
     */
    public function reverseTransform($value)
    {
        if (null === $value) {
            return null;
        }

        if (!is_string($value)) {
            throw new TransformationFailedException('Expected a string.');
        }

        return $this->trueValue === $value;
    }
}

@xabbuh
Copy link
Member
xabbuh commented Feb 9, 2016

closing as a duplicate of #17677

@xabbuh xabbuh closed this as completed Feb 9, 2016
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

5 participants
0