Overview: Foreach VariantGroup
in a Products
VariantSets
I need to create a dropdown containg that VariantGroups
Variants
in the Symfony form
Details:
I have a Product
entity which is associated as a ManyToMany
relationship to multiple VariantSet
objects. The VariantSet
objects contain multiple VariantGroup
objects which need to generate a dropdown each to display their Variant
choices.
For the nested CollectionTypes
I need to only make accessible the options related to the parent CollectionType
.
So the only Variants
available should be related to the VariantGroups
which are only the ones related to the available VariantSets
which are associated to the initially parsed Product
.
There is some info out there that points toward using the query builder to grab the relevant items only but I'm wondering if this is best practice. Also - how do I pass the previous forms (so getting the top level Product
in the nested CollectionType
for VariantGroup
as VariantSets
sits between these two).
Is this even possible to achieve using best practices in Symfony forms?
Example of the desired output here
Yep. The answer was nested CollectionType
forms and a custom query builder in the final form (for some reason it was calling all of the Variant
objects in the DB, rather than using the ones associated to the parsed VariantGroup
object:
Main product form
class ComplexProductType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
// Render the variant sets based on the parsed product
$builder
->add('variantSets', CollectionType::class, [
'entry_type' => VariantSetComplexProductType::class,
'label'=> false,
'by_reference' => true,
] );
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
"data_class" => Product::class,
));
}
}
Render the products Variant Sets: (to get the correct VariantGroups
associated to the main products VarianSet
objects)
class VariantSetComplexProductType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
// Render the groups based on the Variant sets
$builder
->add( 'label' )
->add( 'variantGroups', CollectionType::class, [
'entry_type' => VariantGroupComplexProductType::class,
'label'=> false,
'by_reference' => true
] )
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults( [
'data_class' => VariantSet::class,
] )
;
}
}
Render the Variant Sets VariantGroups
with its Variants
in a dropdown:
The drop down of Variant
objects needs to be done in a FromEvent
using the query_builder
options, as otherwise I had an issue where all the Variant
objects were being called in the DB.
There need to be a check to make sure only the correct Variant
objects were called based on the parsed VariantGroup
.
class VariantGroupComplexProductType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
// Render the drop downs based on the Parsed variant group
$builder
->add( 'label' )
// Rendering of the drop down must be done after the previous form data is available
->addEventListener(FormEvents::PRE_SET_DATA, [$this, 'preSetData']);
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults( [
'data_class' => VariantGroup::class,
] );
}
public function preSetData(FormEvent $event)
{
$form = $event->getForm();
/** @var VariantGroup $child */
$child = $event->getData();
$form
->add('variants', EntityType::class, array(
'class' => Variant::class,
'by_reference' => true,
'query_builder' => function (EntityRepository $er) use ( $child ) {
return $er->createQueryBuilder('u')
->where('u.variant_group = :variant_group')
->setParameter('variant_group', $child )
->orderBy('u.label', 'DESC');
},
'choice_label' => 'label',
));
}
}