在Symfony2中,有没有办法将实体中的更多字段映射到从基于实体的表单生成的选择下拉列表的选项标签?
我目前有类似的东西:
$builder->add('creditcard', 'entity',
array( 'label' => 'Credit Card',
'required' => true,
'expanded' => false,
'class' => 'Acme\Bundle\Entity\CreditCard',
'property' => 'display_text',
'multiple' => false,
'query_builder' => function(\Acme\Bundle\Repository\CreditCardRepository $er) {
return $er->createQueryBuilder('b');
},
'mapped' => false,
));
这很好用,但我想生成类似的东西:
<option value="id" string_mapped_from_field1="value_of_field1">display_text</option>
谢谢!
答案 0 :(得分:14)
好的,如果有人带着同样的问题来到这里,这就是我最后所做的:
我已经创建了自定义字段类型(请参阅http://symfony.com/doc/current/cookbook/form/create_custom_field_type.html)
由于我们最终将成为一个实体字段,您需要添加:
public function getParent() {
return 'entity';
}
在表格上使用时:
$builder->add('creditcard', new CreditCardFieldType(),
array( 'label' => 'Credit Card',
'required' => true,
'expanded' => false,
'class' => 'Acme\Bundle\Entity\CreditCardCharge',
'property' => 'object',
'multiple' => false,
'query_builder' => function(\Acme\Bundle\Repository\CreditCardChargeRepository $er) {
return $er->createQueryBuilder('b');
},
'mapped' => false,
));
object是添加到包含整个对象的实体的新属性,因此我添加到实体:
public function getObject()
{
return $this;
}
这样我们就可以从模板中访问对象了,我们只需要为自己的自定义字段类型创建一个新模板:
{% block creditcard_widget %}
{% spaceless %}
{% if required and empty_value is none and not empty_value_in_choices %}
{% set required = false %}
{% endif %}
<select {{ block('widget_attributes') }}{% if multiple %} multiple="multiple"{% endif %}>
{% if empty_value is not none %}
<option value=""{% if required and value is empty %} selected="selected"{% endif %}>{{ empty_value|trans({}, translation_domain) }}</option>
{% endif %}
{% if preferred_choices|length > 0 %}
{% set options = preferred_choices %}
{{ block('choice_creditcard_widget_options') }}
{% if choices|length > 0 and separator is not none %}
<option disabled="disabled">{{ separator }}</option>
{% endif %}
{% endif %}
{% set options = choices %}
{{ block('choice_creditcard_widget_options') }}
</select>
{% endspaceless %}
{% endblock creditcard_widget %}
{% block choice_creditcard_widget_options %}
{% spaceless %}
{% for group_label, choice in options %}
{% if choice is iterable %}
<optgroup label="{{ group_label|trans({}, translation_domain) }}">
{% set options = choice %}
{{ block('choice_creditcard_widget_options') }}
</optgroup>
{% else %}
<option value="{{ choice.data.creditcard }}" charge="{{ choice.data.charge }}" {% if choice is selectedchoice(data.creditcard_charges_id) %} selected="selected"{% endif %}>{{ choice.data.text|trans({}, translation_domain) }}</option>
{% endif %}
{% endfor %}
{% endspaceless %}
{% endblock choice_creditcard_widget_options %}
在config.yml中注册twig:
twig:
form:
resources:
- 'AcmeBundle:Form:creditcardfield.html.twig'
不确定它是最好的解决方案,但它可以解决问题。希望它有所帮助。
答案 1 :(得分:3)
另一个解决方案是在CreditCardCharge实体上声明函数__toString()
http://symfony.com/doc/current/reference/forms/types/entity.html#property
喜欢:
public function __toString(){
return $this->data1.'-'.$this->data2;
}
此函数必须返回一个字符串,用你的逻辑
替换我的样本并删除“property”选项以默认使用此功能
$builder->add('creditcard', 'entity',
array( 'label' => 'Credit Card',
'required' => true,
'expanded' => false,
'class' => 'Acme\Bundle\Entity\CreditCard',
'multiple' => false,
'query_builder' => function(\Acme\Bundle\Repository\CreditCardRepository $er) {
return $er->createQueryBuilder('b');
},
'mapped' => false,
));
答案 2 :(得分:1)
我把它放在我的empField.php中修复了它:
{%- block choice_widget_options -%}
{% for group_label, choice in options %}
{%- if choice is iterable -%}
<optgroup label="{{ group_label|trans({}, translation_domain) }}">
{% set options = choice %}
{{- block('choice_widget_options') -}}
</optgroup>
{%- else -%}
<option value="{{ choice.value }}" data-position="{{ choice.data.position }}" data-avatar="{% path choice.data.avatar, 'reference' %}"{% if choice is selectedchoice(value) %} selected="selected"{% endif %}>{{ choice.data.fullname }}</option>
{%- endif -%}
{% endfor %}
{%- endblock choice_widget_options -%}
(来自:\ vendor \ symfony \ symfony \ src \ Symfony \ Bridge \ Twig \ Resources \ views \ Form \ form_div_layout.html.twig) 它有效,我不确定这是正确的做法,但它是否有效。
答案 3 :(得分:0)
我试图在我的实体中使用这个例子,但我有一个问题。它不会检测页面加载后是否选择了值,并且在提交后它不会保留。
我觉得这与这一行有关:
<option value="{{ choice.data.creditcard }}" charge="{{ choice.data.charge }}" {% if choice is selectedchoice(data.creditcard_charges_id) %} selected="selected"{% endif %}>{{ choice.data.text|trans({}, translation_domain) }}</option>
我不确定要理解要放的内容而不是: data.creditcard_charges_id 。
这就是我的看法:
{% block emp_widget %}
{% spaceless %}
{% if required and empty_value is none and not empty_value_in_choices %}
{% set required = false %}
{% endif %}
<select {{ block('widget_attributes') }}{% if multiple %} multiple="multiple"{% endif %}>
{% if empty_value is not none %}
<option value=""{% if required and value is empty %} selected="selected"{% endif %}>{{ empty_value|trans({}, translation_domain) }}</option>
{% endif %}
{% if preferred_choices|length > 0 %}
{% set options = preferred_choices %}
{{ block('choice_emp_widget_options') }}
{% if choices|length > 0 and separator is not none %}
<option disabled="disabled">{{ separator }}</option>
{% endif %}
{% endif %}
{% set options = choices %}
{{ block('choice_emp_widget_options') }}
</select>
{% endspaceless %}
{% endblock emp_widget %}
{% block choice_emp_widget_options %}
{% spaceless %}
{% for group_label, choice in options %}
{% if choice is iterable %}
<optgroup label="{{ group_label|trans({}, translation_domain) }}">
{% set options = choice %}
{{ block('choice_emp_widget_options') }}
</optgroup>
{% else %}
<option value="{{ choice.data.id }}" data-position="{{ choice.data.position }}" data-avatar="{% path choice.data.avatar, 'reference' %}" {% if choice is selectedchoice(choice.data.id) %} selected="selected"{% endif %}>{{ choice.data.firstname }} {{ choice.data.lastname }}</option>
{% endif %}
{% endfor %}
{% endspaceless %}
{% endblock choice_emp_widget_options %}