如何擴充套件 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,並在填充新選項時執行資料轉換。