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
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.