如何扩展 ChoiceType EntityType 和 DocumentType 以使用 AJAX 加载选项

在 Symfony 中,内置的 ChoiceType(以及扩展它的 EntityType 或 DocumentType)基本上使用常量选择列表。

如果你想让它与 ajax 调用一起工作,你必须改变它们以接受任何额外的额外选择。

  • 如何从空选择列表开始?

    在构建表单时,只需将 choices 选项设置为空的 array()

     namespace AppBundle\Form;
    
     use Symfony\Component\Form\AbstractType;
    
     use Symfony\Component\Form\FormBuilderInterface;
    
     use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
    
     class FooType extends AbstractType
     {
         public function buildForm(FormBuilderInterface $builder, array $options)
         {
             $builder
                 ->add('tag', ChoiceType::class, array('choices'=>array()));
         }
     }
    

    因此,你将获得一个空的选择输入,没有选择。此解决方案适用于 ChoiceType 及其所有子项(EntityType,DocumentType,…)。

  • 如何接受提交的新选择

    要接受新选项,你必须在表单字段选择列表中使用它们。你可以使用 FormEvent::PRE_SUBMIT 事件根据提交的数据更改表单字段。

    此示例显示如何使用基本 ChoiceType 执行此操作:

     namespace AppBundle\Form;
    
     use Symfony\Component\Form\AbstractType;
    
     use Symfony\Component\Form\FormBuilderInterface;
    
     use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
    
     class FooType extends AbstractType
     {
         public function buildForm(FormBuilderInterface $builder, array $options)
         {
             $builder
                 ->add('tag', ChoiceType::class, array('choices'=>array()))
             ;
    
             $builder->addEventListener(
                 FormEvents::PRE_SUBMIT,
                 function(FormEvent $event){
                     // Get the parent form
                     $form = $event->getForm();
    
                     // Get the data for the choice field
                     $data = $event->getData()['tag'];
    
                     // Collect the new choices
                     $choices = array();
    
                     if(is_array($data)){
                         foreach($data as $choice){
                             $choices[$choice] = $choice;
                         }
                     }
                     else{
                         $choices[$data] = $data;
                     }
    
                     // Add the field again, with the new choices :
                     $form->add('tag', ChoiceType::class, array('choices'=>$choices));
                 }
             );
         }
     }
    

    你提交的选项现在是允许的选择,Symfony ChoiceType 内置验证将不再拒绝它们。

    如果你想对 ChoiceType 子项(EntityType,DocumentType,…)执行相同操作,则必须注入 entityManager 或 documentManager,并在填充新选项时执行数据转换。