我想在Symfony中创建表单时使用条件语句。
我在一般情况下使用选择小部件。如果用户选择“其他”选项,我想显示其他文本框小部件。我想这可以在javascript中完成,但是我怎样才能将来自2个小部件的数据保存到我的实体中的同一个属性中?
到目前为止,我有这个:
$builder->add('menu', 'choice', array(
'choices' => array('Option 1' => 'Option 1', 'Other' => 'Other'),
'required' => false,
));
//How to add text box if choice == Other ????
我计划使用DataTransfomer,但是在2个小部件上?
答案 0 :(得分:33)
我建议为其构建自定义类型,例如ChoiceOrTextType
。对于此类型,您可以添加选项(名为“choice”)和文本字段(名为“text”)。
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class ChoiceOrTextType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('choice', 'choice', array(
'choices' => $options['choices'] + array('Other' => 'Other'),
'required' => false,
))
->add('text', 'text', array(
'required' => false,
))
->addModelTransformer(new ValueToChoiceOrTextTransformer($options['choices']))
;
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setRequired(array('choices'));
$resolver->setAllowedTypes(array('choices' => 'array'));
}
}
正如您已经猜到的,您还需要一个数据转换器,这可以非常简单:
use Symfony\Component\Form\DataTransformerInterface;
class ValueToChoiceOrTextTransformer implements DataTransformerInterface
{
private $choices;
public function __construct(array $choices)
{
$this->choices = $choices;
}
public function transform($data)
{
if (in_array($data, $this->choices, true)) {
return array('choice' => $data, 'text' => null);
}
return array('choice' => 'Other', 'text' => $data);
}
public function reverseTransform($data)
{
if ('Other' === $data['choice']) {
return $data['text'];
}
return $data['choice'];
}
}
现在只将“菜单”字段设为该类型的字段。
$builder->add('menu', new ChoiceOrTextType(), array(
'choices' => array('Option 1' => 'Option 1', 'Option 2' => 'Option 2'),
'required' => false,
));