Symfony Форма: Как применить разные темы / виджеты к указанным c полям формы? - PullRequest
1 голос
/ 08 мая 2020

Форма на основе Symfony 3.4 содержит несколько полей CheckboxType. Некоторые из этих полей должны отображаться как обычные флажки (= с использованием виджета флажков по умолчанию), а некоторые другие должны отображаться как переключатели включения / выключения (например, iOS UISwitche).

Итак, внутри одной формы поля одного и того же типа (CheckboxType) должны использовать разные виджеты. Как я могу это сделать?


Решение 1: Конечно, я могу применить пользовательский form_theme к полной форме ({% form_theme form 'AppBundle:Form:myTheme.html.twig' %}). Но это эффект всех чекбоксов внутри формы, а не только одного. Так что это не решение.


Решение 2: Решение, которое будет работать, - применить другой виджет к одному определенному полю c, используя его идентификатор:

{% block _user_registration_form_someCheckBoxRow %}
    ...
{% endblock %}

Пока это решение работает, мне пришлось бы создавать / переопределять одни и те же блоки для всех задействованных полей во всех задействованных формах. Это довольно громоздкое и поэтому не очень хорошее решение.


Решение 3: Другое решение, которое будет работать, - создать собственный FormType, который будет использоваться флажками, которые должны отображаться как переключатели. Этот тип формы будет расширять CheckboxType и ничего не делать, кроме как переопределять blockPrefix.

Хотя это довольно близко к хорошему решению, есть один серьезный недостаток: предположим, что существуют разные темы / виджеты для переключателей флажков. Один с меткой сверху, другой с меткой рядом с переключателем и т. Д. c. Для каждого из этих стилей потребуется не только собственный виджет, но и свой собственный тип формы, который необходимо зарегистрировать в FormPass.php, et c. Это, конечно, сработает, но также довольно громоздко и подвержено ошибкам.

Итак, это было бы решением, но не nice.


Нет лучшего способа ? Я искал что-то вроде {{ form_row(form.someCheckbox, 'someWidget') }}. Для каждой темы будет только один дополнительный файл, и можно будет точно сказать, какое поле использует какую тему. Никаких дополнительных классов, конфигов и т. Д. c. необходимо. Ничего подобного не нашел.

Действительно ли использование фиктивных форм является лучшим решением?

Ответы [ 2 ]

1 голос
/ 08 мая 2020

Ссылаясь на мой последний комментарий выше, следующее работает с Symfony 5.0.x (хотя никаких серьезных изменений для 3.4 не требуется, возможно только некоторая дополнительная конфигурация):

Чтобы абстрагироваться от обработки темы, определите свой собственный тип флажка, как показано ниже (например):

<?php
declare(strict_types=1);

namespace App\Form\Type;

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

class ThemedCheckboxType extends AbstractType
{
    /**
     * @param OptionsResolver $resolver
     */
    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver
            ->setDefaults([
                'theme' => 'default',
                'block_prefix' => static function (Options $options): ?string {
                    return [
                        'default' => null,
                        'theme-a' => 'theme_a_checkbox',
                        'theme-b' => 'theme_b_checkbox',
                    ][$options['theme']];
                },
            ])
            ->setAllowedValues('theme', ['default', 'theme-a', 'theme-b']);
    }

    /**
     * @inheritDoc
     */
    public function getParent(): string
    {
        return CheckboxType::class;
    }
}

Затем просто используйте его там, где это необходимо, например:

$builder->add('test_a1', ThemedCheckboxType::class, [
    'theme' => 'theme-a', // or others
]);

Таким образом, вы можете ввести свою собственную форму тема, чтобы напрямую манипулировать флажками, когда это необходимо, например,

{% block theme_a_checkbox_widget %}
    <em>Theme-A</em>
    {{ block('checkbox_widget') }}
{% endblock %}

{% block theme_b_checkbox_widget %}
    <em>Theme-B</em>
    {{ block('checkbox_widget') }}
{% endblock %}

Если вы не хотите использовать дополнительный тип формы, то же самое можно сделать, используя расширение настраиваемой формы для добавления параметров в тип флажка по умолчанию. См .: https://symfony.com/doc/current/form/create_form_type_extension.html

Например:

<?php
declare(strict_types=1);

namespace App\Form\Extension;

use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolver;

class CheckboxTypeExtension extends AbstractTypeExtension
{
    /**
     * @inheritDoc
     */
    public static function getExtendedTypes(): iterable
    {
        return [CheckboxType::class];
    }

    /**
     * @inheritDoc
     */
    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver
            ->setDefaults([
                'theme' => 'default',
                'block_prefix' => static function (Options $options): ?string {
                    return [
                        'default' => null,
                        'theme-a' => 'theme_a_checkbox',
                        'theme-b' => 'theme_b_checkbox',
                    ][$options['theme']];
                },
            ])
            ->setAllowedValues('theme', ['default', 'theme-a', 'theme-b']);
    }
}

, что позволяет:

$builder->add('test_a1', CheckboxType::class, [
    'theme' => 'theme-a',
]);
0 голосов
/ 08 мая 2020

Вы можете применить тему к одному флажку:

{% form_theme form.my_special_checkbox 'Form/Theme/special_checkbox.html.twig' %}

Или, если вам не нужна отдельная тема (один вариант использования), вы можете писать блоки в текущем Файл Twig:

{% block _my_checkbox_widget_block %}
    {# the theme #}
{% endblock %}

{% form_theme form.my_special_checkbox _self %}

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

...