Symfony - Entity Type Field with Select2

Viewed 468

I have the following problem. I have two tables in my Symony 6 project:

  1. Articles
  2. Variants

These two tables are linked to each other in that an article can have several variants and a variant always belongs to one article.

Now I have a form to create a new variant in which I have to select the corresponding article. For this I want to use the EntityType Field as a dropdown.

The problem is that I have up to 100,000 articles in the article table which causes hughe loading problems when loading all options at once. Therefore, I thought about using Select2 so that a query is only made after 1-2 characters have been entered and only the articles that match the search are displayed in the dropdown.

JS:

    $(#sizes).select2({
        ajax: {
            url: {{ path("text_ajax_load_select_option") }},
            dataType: 'json',
            type: 'GET',
            data: function (params) {
    
                var queryParameters = {
                    term: params.term,
                }
                return queryParameters;
            },                
            processResults: function (data) {
                return {
                    results: $.map(data.selectOptions, function (selectOptions) {
                        return {
                            text: selectOptions.title,
                            id: selectOptions.title
                        }
                    })
                };
            }
        }
    }) 

New Form (VariantenType) with the EntityType Dropdown to populate dynamically based on search input in select2 field:

    public function buildForm(FormBuilderInterface $builder, array $options): void
    {

        $builder
           // .. other         
            ->add('base_article', EntityType::class, [
                'class' => Artikel::class,
                'multiple' => false,
                'choice_label' => 'title', 
                'label' => 'Base Article',
                'choices' => [],
            ])         
        ;
    }
    

I would be happy about any ideas and suggestions.

1 Answers

You just need to add a PRE_SUBMIT event listener to your FormBuilder:

public function buildForm(FormBuilderInterface $builder, array $options): void
{
      $builder
        // ... other properties         
        ->add('base_article', EntityType::class, [
            'class' => Artikel::class,
            'choice_label' => 'title', 
            'label' => 'Base Article',
            'choices' => [],
            'attr' => [
                'class' => 'select2article'
            ]  
        ]); 

       $builder->addEventListener(
            FormEvents::PRE_SUBMIT,
            function (FormEvent $event) {
                $data = $event->getData();
                $form = $event->getForm();
                if(isset($data['base_article']) and $data['base_article']!=null){
                    $selected = $data['base_article'];
                    $form->add('base_article', EntityType::class, array(
                        'class' => Artikel::class,
                        'choice_label' => 'title',
                        'label' => 'Base Article',
                        'attr' => [
                           'class' => 'select2article'
                        ],
                        'query_builder' => function (EntityRepository $er) use  ($selected){
                            return $er->createQueryBuilder('a')
                                ->where('a.id = :id')
                                ->setParameter('id', $selected);
                        },
                    ));
                }  
            }
        );
}

JS

  $('.select2article').select2({
        ajax: {
            url: {{ path("text_ajax_load_select_option") }},
            dataType: 'json',
            type: 'GET',
            data: function (params) { 
                var queryParameters = {
                    term: params.term,
                }
                return queryParameters;
            },                
            processResults: function (data) {
                return {
                    results: $.map(data.selectOptions, function (selectOptions) {
                        return {
                            text: selectOptions.title,
                            id: selectOptions.id
                        }
                    })
                };
            }
        }
    })

So after sending the request, we get into our event listener. There we will get the selected id of the base_article property, after which we will add the query_builder parameter to the form with the selection by id from the Artikel entity

Related