Формы Symfony5 - отображать радио-ввод внутри метки

Я хочу отображать входы типа радио внутри их меток, потому что я хочу использовать flexbox, чтобы оправдать их пробелами между ними.

Вот часть класса RegistrationType

...
        ->add('gender', ChoiceType::class, [
            'required' => true,
            'expanded' => true,
            'multiple' => false,
            'label' => false,
            'choices' => [
                'male' => 'male',
                'female' => 'female',
                'other' => 'other',
            ],
        ])

Параметры настройки этого класса установлены по умолчанию:

public function configureOptions(OptionsResolver $resolver)
{
    $resolver->setDefaults([
        'data_class' => User::class,
    ]);
}

Я хочу добиться данного результата:

<div style="display:flex; flex-direction:row; justify-content:space-between; width:22rem;">
                <label>
                    <input  type="radio" 
                            name="registration_form[gender]" 
                            required="required" 
                            class="required" 
                            value="male">

                            Male
                </label>
                
                <label>
                    <input  type="radio" 
                            name="registration_form[gender]" 
                            required="required" 
                            class="required" 
                            value="female">

                            Female
                </label>
                
                <label>
                    <input  type="radio" 
                            name="registration_form[gender]" 
                            required="required" 
                            class="required" 
                            value="other">

                            Other
                </label>
                
            </div>

Есть какой-либо способ сделать это?


person Przemek Kro    schedule 01.09.2020    source источник


Ответы (1)


Подобно принятому ответу здесь и поддерживается Переменные поля класса ChoiceType, вы можете получить доступ к атрибуту .choices и перебрать его так:

<div style="display:flex; flex-direction:row; justify-content:space-between; width:22rem;">
    {{ form_label(form.gender) }}
    <div>
    {% for key,val in form.gender.vars.choices %}
    <label>
        <input type="radio" 
            name="{{ form.gender.vars.full_name }}" 
            required="required"
            class="required"
            value="{{ val.value }}"
        />
        {{ val.label | trans }} />
    {% endfor %}
    </div>
</div>

Существуют более элегантные способы настройки, например создание или переопределение темы формы, или, возможно, используя макрос twig, чтобы сохранить ваш код несколько СУХОЙ. Если вы идете по пути темы формы, обратите внимание на то, как атрибуты блокируют используется — мы обходим большую часть полезности, которую он дает в этом примере выше.

person Cameron Hurd    schedule 01.09.2020
comment
Спасибо! Ваше решение работает, как и ожидалось, после незначительных изменений. Темы форм выглядят интересно, и я буду читать больше о них и макросах. Я только новичок в использовании Symfony. - person Przemek Kro; 02.09.2020
comment
Я бы добавил, что даже если элемент формы был отрендерен, symfony все равно отрисовывает его в конце. Я не понимаю этот механизм, но кажется, что symfony должен отображать все элементы формы, если они не указаны между form_start и form_end в twig. Данное решение не предотвращает такое поведение. - person Przemek Kro; 02.09.2020
comment
Хороший улов! Если вы уверены, что ваш шаблон отображает все, что нужно для рендеринга, закройте с помощью form_end(form, {'render_rest': false}). (В противном случае переопределение темы будет использовать form_widget и сигнализировать о том, что поле уже обработано.) - person Cameron Hurd; 02.09.2020
comment
Работает и все идеально. Спасибо еще раз. :-) - person Przemek Kro; 02.09.2020