我在理解Symfony2 自定义表单字段类型的工作方式时遇到了一些麻烦。我需要根据传递给data-*
的数据创建一个包含一些自定义属性(HTML5 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'; }
}
答案 0 :(得分:1)
所以基本问题是标签会获取窗口小部件上的所有属性。我真的不明白为什么他们这样设计它,但如果你看一下:
{# 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块只显示for和class属性,这是我到目前为止所需要的。同样,默认的实现是令人困惑的,我可能错过了一些明显的东西,但覆盖似乎工作正常。使用form_theme引入新的表单文件:
{% form_theme form 'ZaysoCoreBundle:Layout:fields.html.twig' %}
答案 1 :(得分:1)
编辑:据我所知,传递array('attr' => array('myattr1' => 'value1'))
作为构建器的选项旨在作为构建器的常用属性以及所有其子元素。这就是为什么,例如,在表单级别传递array('required' => false)
将禁用该表单中每个字段的HTML5内置客户端验证。
(一直在寻找更好的解决方案)我会发布自己的方式,受到blog post的启发:自定义表单字段,查看属性和 Twig block 以创建新属性。
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) }}