10000 [Form] Conflict between empty Placeholder value and false value in ChoiceType · Issue #17677 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

[Form] Conflict between empty Placeholder value and false value in ChoiceType #17677

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
raziel057 opened this issue Feb 4, 2016 · 4 comments
Closed

Comments

@raziel057
Copy link
Contributor

Using Symfony 2.8.2 or 3.0.2.
You can reproduce the problem with this simple statement:

$builder->add('participation', ChoiceType::class, array(
     'choices' => [ 'yes' => true, 'no' => false ],
    'placeholder' => 'Select a value',
    'empty_data' => null,
    'choices_as_values' => true,
));

Expected result:

<select name="filter[participation]" id="filter_participation">
    <option value="">Select a value</option>
    <option value="1">Yes</option>
    <option selected="selected" value="0">No</option>
</select>

Actual result:

<select name="filter[participation]" id="filter_participation">
    <option value="1">Yes</option>
    <option selected="selected" value="">No</option>
</select>

Dump of choiceList:

boolean_choice_dump

As you can see, the placeholder is not rendered. If I add a new empty value in 'choices', I got an empty value in the view plus the placeholder value.

@raziel057 raziel057 changed the title [Form] Placeholder doesn't works for one case in ChoiceType [Form] Conflict between empty Placeholder value and false value in ChoiceType Feb 8, 2016
@HeahDude
Copy link
Contributor

Hi @raziel057, the workaround is to use choice_value option as below :

$builder->add('participation', ChoiceType::class, array(
'choices' => [ 'yes' => true, 'no' => false ],
'choice_value' => function ($choice) {
return false === $choice ? '0' : (string) $choice;
},
'placeholder' => 'Select a value',
'empty_data' => null,
'choices_as_values' => true,
));

see #17759 for my proposal to fix it.

@HeahDude
Copy link
Contributor

Bug confirmed.
Status: reviewed

@raziel057
Copy link
Contributor Author

@HeahDude Yes in fact, to avoid to use this workarround in all my fields, I created a custom BooleanType with a DataTransformer to be able to use it like this:

$builder->add('interpretation', PtcBooleanType::class, array(
    'label' => 'enabled',
    'required' => false,
));
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 11, 2016

closing here as a duplicate of #17292

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