Home > OS >  Symfony 6 : can't get collection in custom FormType
Symfony 6 : can't get collection in custom FormType

Time:10-19

I have two entities, Formation and Theme. A Theme can have many Formation and Formation can belong to many Theme. Inside the add form for Formation, I would like to display a select of themes that looks like the image below enter image description here

I created a custom FormType called SearchableEntityType but in this latter, I can't get the themes. When I dd($form->getdata()), it's empty. What do I miss ? Thanks for any help.

Here is the code of Entity/Formation.php

<?php

namespace App\Form;

use App\Entity\Formation;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class FormationType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('label')
            ->add('themes' , SearchableEntityType::class, [
                'class' => Theme::class
            ])
        ;
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            'data_class' => Formation::class,
        ]);
    }
}

Entity/Theme.php

<?php

namespace App\Form;

use App\Entity\Theme;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class ThemeType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('label')
            ->add('color')
            ->add('shortDescription')
        ;
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            'data_class' => Theme::class,
        ]);
    }
}

Form/FormationType.php

<?php

namespace App\Form;

use App\Entity\Formation;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class FormationType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('label')
            ->add('themes' , SearchableEntityType::class, [
                'class' => Theme::class
            ])
        ;
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            'data_class' => Formation::class,
        ]);
    }
}

Form/SearchableEntityType.php

<?php

namespace App\Form;

use App\Entity\Theme;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\ChoiceList\View\ChoiceView;
use Symfony\Component\OptionsResolver\OptionsResolver;

class SearchableEntityType extends AbstractType
{
  public function configureOptions(OptionsResolver $resolver) {
    $resolver->setRequired('class');
    $resolver->setDefaults([
      'compound' => false,
      'multiple' => true
    ]);
  }

  public function getBlockPrefix() {
    return 'choice';
  }

  public function buildView(FormView $view, FormInterface $form, array $options) {

    dd($form);
    
    $view->vars['expanded'] = false;
    $view->vars['placeholder'] = null;
    $view->vars['placeholder_in_choices'] = false;
    $view->vars['multiple'] = true;
    $view->vars['preferred_choices'] = $this->choices($form->getData());
    $view->vars['choices'] = [];
    $view->vars['choice_translation_domain'] = false;
    $view->vars['full_name'] .= '[]';
  }

  private function choices(Collection $value) {

;    return $value
      ->map(fn ($d) => new ChoiceView($d, (string)$d->getId(), (string)$d))
      ->toArray();
  }
}

CodePudding user response:

Looking at your current SearchableEntityType, I don't think it's necessary at all.

You could just use symfony EntityType and configure it like your SearchableEntityType:

<?php

namespace App\Form;

use App\Entity\Formation;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class FormationType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('label')
            ->add('themes', EntityType::class, [
                'class' => Theme::class,
                'multiple' => true,
                'choice_label' => 'label',
                'label' => 'Thèmes',
            ])
        ;
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            'data_class' => Formation::class,
        ]);
    }
}

And if you want to use optgroup to have a better display you can look into group_by to choose a way to define a group name for each option.

  • Related