Andrei Herford
Andrei Herford

Reputation: 18729

How to use custom values in Symfony 2.7 choice form field instead of numbers

I am struggling with using choice form fields in Symfony 2.7. The goal is to let the user select some very basic options:

Data Object

class MyDataObj {
    protected $option = null;

    public function getOption() {
        return $this->option;
    }

    public function setOption($option) {
        $this->option = $option;
    }
}

Form creation within some controller:

...
$dataObject = new MyDataObject();
$form = $this->createForm('custom_data_type', $dataObject);
$form->handleRequest($request);

if ($form->isValid()) {
    ...
}

The custom FormType

public function buildForm(FormBuilderInterface $builder, array $options) {
    $builder
        ->add('option', 'choice', array(
            ...
            'choices' => array(
                'Option A' => 'option_value_1',
                'Option B' => 'option_value_2',
                'Option C' => 'option_value_3',
                ),
            'choices_as_values' => true,   
        ));

    ...
}

The rendered Result:

<select id="custom_data_type_option" class="form-control" name="custom_data_type[option]">
    <option value="0">Option A</option>
    <option value="1">Option B</option>        
    <option value="2">Option C</option>
</select>

So the Options get the values 0-2 instead of option_value_N. How can I change this?

I already tried to add a choice_value callback. However, the result was even more irritating :

->add('option', 'choice', array(
    ...
    'choices' => array(
        'Option A' => 'option_value_1',
        'Option B' => 'option_value_2',
        'Option C' => 'option_value_3',
    ),
    'choices_as_values' => true,  
    'choice_value' => function ($allChoices, $currentChoiceKey) { 
        if (null === $currentChoiceKey) 
            return 'nothing';

        if ('Option A' === $currentChoiceKey) 
            return 'option_value_1';

        if ('Option B' === $currentChoiceKey) 
            return 'option_value_2';

        if ('Option C' === $currentChoiceKey) 
            return 'option_value_3'; 

        return 'unknown';
    }
));

THE RESULT:
<select id="custom_data_type_option" class="form-control" name="custom_data_type[option]">
    <option value="nothing">Option C</option>
    <option value="nothing">Option C</option>        
    <option value="nothing">Option C</option>
</select>

I do understand, that before Symfony 2.7 the handling was different and a choice key => value was rendered as <option value="key">value</option>. To turn of this behaviour in Symfony 2.7 the 'choices_as_values' => true option has to be used.

But I do not understand, why the values are not simply used as specified in choices (which is a key => value array)...

And what is wrong with the choice_value callback that delivers such a strange result?

Upvotes: 1

Views: 2562

Answers (2)

Al Foиce    ѫ
Al Foиce ѫ

Reputation: 4315

This is how I do and it's working well (but Symfony 2.8). I defined my array without reversing keys and use the php array_flip() method :

use Symfony\Component\Form\Extension\Core\Type\ChoiceType;

$myArray = [
    'option_value_1' => 'Option A',
    'option_value_2' => 'Option B',
    'option_value_3' => 'Option C',
];

$builder->add('mySelect', ChoiceType::class, [
    'choices' => array_flip($myArray),
    'choices_as_values' => true,
]);

The rendering using Twig:

{{ form_widget(form.mySelect) }}

PS: advice: avoid using names as 'option' as varaiable or key names...

Upvotes: 1

yceruto
yceruto

Reputation: 9585

So the Options get the values 0-2 instead of option_value_N. How can I change this?

The way to generate the "choices" option has changed since the version 2.7, if the choice_value option is null, an incrementing integer is used as the value.

And what is wrong with the choice_value callback that delivers such a strange result?

if you need to keep the values in the final <select> then only have to do this:

->add('option', 'choice', array(
    'choices' => array(
        'Option A' => 'option_value_1',
        'Option B' => 'option_value_2',
        'Option C' => 'option_value_3',
    ),
    'choices_as_values' => true,
    // this will keep the same functionality as before
    'choice_value' => function ($value, $key, $index) {
        return $value;
    }
));

THE RESULT:
<select id="custom_data_type_option" class="form-control" name="custom_data_type[option]">
    <option value="option_value_1">Option C</option>
    <option value="option_value_2">Option C</option>
    <option value="option_value_3">Option C</option>
</select>

Refs:

Upvotes: 2

Related Questions