Поиск…


Как расширить 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 и сделать datatransformation при заполнении новых вариантов.

Заполните поле выбора в зависимости от значения другого.

Это пример, показывающий, как изменить разрешенные варианты в поле выбора подкатегории в зависимости от значения поля выбора категории. Для этого вы должны сделать выбор своей подкатегории динамичным как для клиента, так и для сервера.

1. Сделайте динамическую форму на стороне клиента для взаимодействия с дисплеем / пользователем

Пример динамической формы клиентской стороны (с использованием Javascript / JQuery):

    $('#category').change(function(){
        switch($(this).val()){
            case '1': // If category == '1'
                var choice = {
                    'choice1_1':'1_1',
                    'choice1_2':'1_2',
                    'choice1_3':'1_3',
                };
            break;
            case '2': // If category == '2'
                var choice = {
                    'choice2_1':'2_1',
                    'choice2_2':'2_2',
                    'choice2_3':'2_3',
                };
            break;
            case '3': // If category == '3'
                var choice = {
                    'choice3_1':'3_1',
                    'choice3_2':'3_2',
                    'choice3_3':'3_3',
                };        
            break;
        }
        
        var $subCategorySelect = $('#subCategory');
        
        $subCategorySelect.empty();
        $.each(choice, function(key, value) {
            $subCategorySelect.append($('<option></option>')).attr('value',value).text(key);
        });
    });

Конечно, вы можете получить выбор из звонка AJAX. Это не цель этого примера.

2. Сделайте динамическую форму на стороне сервера для инициализации / проверки

Пример динамической формы на стороне сервера:

    namespace AppBundle\Form;

    use Symfony\Component\Form\AbstractType;
    use Symfony\Component\Form\FormBuilderInterface;

    use Symfony\Component\Form\Extension\Core\Type\ChoiceType;

    use Symfony\Component\Form\FormEvent;
    use Symfony\Component\Form\FormEvents;

    class MyBaseFormType extends AbstractType
    {
        /**
         * @param FormBuilderInterface $builder
         * @param array $options
         */
        public function buildForm(FormBuilderInterface $builder, array $options)
        {
            $builder
                ->add('category',ChoiceType::class,array('choices'=>array(
                        'choice1'=>'1',
                        'choice2'=>'2',
                        'choice3'=>'3',
                    )))
            ;
            
            $addSubCategoryListener = function(FormEvent $event){
                $form = $event->getForm();
                $data = $event->getData();
                
                switch($data['category']){
                    case '1': // If category == '1'
                        $choices = array(
                            'choice1_1'=>'1_1',
                            'choice1_2'=>'1_2',
                            'choice1_3'=>'1_3',
                        );
                    break;
                    case '2': // If category == '2'
                        $choices = array(
                            'choice2_1'=>'2_1',
                            'choice2_2'=>'2_2',
                            'choice2_3'=>'2_3',
                        );                        
                    break;
                    case '3': // If category == '3'
                        $choices = array(
                            'choice3_1'=>'3_1',
                            'choice3_2'=>'3_2',
                            'choice3_3'=>'3_3',
                        );                        
                    break;
                }
                
                $form->add('subCategory',ChoiceType::class,array('choices'=>$choices));
            };
            
            // This listener will adapt the form with the data passed to the form during construction :
            $builder->addEventListener(FormEvents::PRE_SET_DATA, $addSubCategoryListener);
            
            // This listener will adapt the form with the submitted data :
            $builder->addEventListener(FormEvents::PRE_SUBMIT, $addSubCategoryListener);
        }
    }


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow