Пользовательское поле формы в Symfony2, нежелательный атрибут унаследован - PullRequest
2 голосов
/ 26 марта 2012

У меня возникают проблемы с пониманием того, как Symfony2 типы полей пользовательских форм работают. Мне нужно создать новый тип с некоторыми пользовательскими атрибутами (HTML5 data-*) на основе данных, переданных в MyType.

Проблема в в том, что после добавления MyType в основную форму ее метка наследует атрибут data-*.

// Add MyType to the main form

$builder->add('somename', new MyType(), array('label' => 'my label'));

Это мой пользовательский тип:

class MyType extends AbstractType
{

    public function getDefaultOptions(array $options)
    {
       $source = isset($option['source']) ? json_encode($option['source']) : '';

        return array(
            'attr' => array(
                'data-source' => $source
            )
        );
    }

    public function getName() { return 'mytype'; }

    public function getParent(array $options) { return 'text'; }

}

Ответы [ 2 ]

1 голос
/ 27 марта 2012

РЕДАКТИРОВАТЬ : насколько я понимаю, передача array('attr' => array('myattr1' => 'value1')) в качестве опции для компоновщика предназначена для общих атрибутов компоновщика и всех его дочерних элементов . Вот почему, например, передача array('required' => false) на уровне формы отключит встроенную проверку HTML5 на стороне клиента для каждого поля внутри этой формы.

(всегда в поисках лучшего решения) я опубликую свой путь, вдохновленный этим сообщением в блоге : настраиваемым полем формы с атрибутами просмотра и Блок Twig для создания новых атрибутов.

class TypeheadType extends AbstractType
{

    public function buildForm(FormBuilder $builder, array $options)
    {
        $builder
            ->setAttribute('mode',  $options['mode'])
            ->setAttribute('items', $options['items']);

    }

    public function buildView(FormView $view, FormInterface $form)
    {

        $view
            ->set('mode',  $form->getAttribute('mode'))
            ->set('items', $form->getAttribute('items'));
    }

    public function getDefaultOptions(array $options)
    {

        return array(
            'mode'  => 'single',
            'items' => 10
        );
    }

    public function getName() { return 'typehead'; }

    public function getParent(array $options) { return 'field'; }

}

Новый тип формы должен быть зарегистрирован как сервис, а псевдоним должен совпадать с тем, что возвращается getName() (это обязательно? Dunno ...):

form.type.typehead:
  class: Acme\HelloBundle\Form\Type\TypeheadType
  tags:
    - { name: form.type, alias: typehead }

Создание нового поля (в другом месте):

$builder->add('myfield', 'typehead', array('items' => 15));

В блоке виджетов темы формы Twig (шаблон для имени as getName() . '_widget) вы можете использовать атрибуты вида, установленные в TypeheadType:

{% block typehead_widget %}
{% spaceless %}
    <input type="text" {{ block('widget_attributes') }} 
        {% if value is not empty %}value="{{ value }}" {% endif %}
        data-items="{{ items }}" data-mode="{{ mode }}" />
{% endspaceless %}
{% endblock typehead_widget %}

И, наконец:

{{ form_row(form.myfield) }}
1 голос
/ 26 марта 2012

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

{# Symfony/Bridge/Twig/Resources/Form/form_div_layout.html.twig #}
{% block generic_label %}
{% spaceless %}
    {% if required %}
        {% set attr = attr|merge({'class': attr.class|default('') ~ ' required'}) %}
    {% endif %}
    <label{% for attrname,attrvalue in attr %} {{attrname}}="{{attrvalue}}"{% endfor%}>{{ label|trans }}</label>
{% endspaceless %}
{% endblock %}

Вы можете видеть, что generic_label (вызывается по умолчанию) сбрасывает каждый атрибут.

Я переопределил значение по умолчанию:

{% block generic_label %}
{% spaceless %}
    {% if required %}
        {% set attr = attr|merge({'class': attr.class|default('') ~ ' required'}) %}
    {% endif %}
    <label {{ block('label_attributes') }}>{{ label|trans }}</label>
{% endspaceless %}
{% endblock %}

{% block label_attributes %}
{% spaceless %}
    {% for attrname,attrvalue in attr %}{% if (attrname == 'for' or attrname == 'class') %} {{attrname}}="{{attrvalue}}"{% endif %}{% endfor %}
{% endspaceless %}
{% endblock %}

Мой блок label_attributes содержит только атрибуты и атрибуты класса, и это все, что мне нужно до сих пор. Опять же, реализация по умолчанию сбивает с толку, и я, вероятно, упускаю что-то очевидное, но переопределение, кажется, работает хорошо. Используйте form_theme для ввода нового файла форм:

{% form_theme form 'ZaysoCoreBundle:Layout:fields.html.twig' %}
...