Custom filter : ChoiceType with "multiple = true" produce an error Undefined array key "comparison"
Describe the bug
When I want to create a custom filter with ChoiceType Symfony field and the option multiple = true, I have an error.
It works only if I set multiple to false.
I use the last EA version (v 4.0.8). I don't want to define a "comparaison", whats is wrong ?
To Reproduce Just create a custom filter like this
class SupplierFilter implements FilterInterface
{
use FilterTrait;
public static function new(string $propertyName, $label = null): self
{
return (new self())
->setFilterFqcn(__CLASS__)
->setProperty($propertyName)
->setLabel($label)
->setFormType(ChoiceType::class)
->setFormTypeOptions([
"choices" => ["Checker" => 1, "Cleaner" => 2],
"multiple" => true,
"expanded" => true,
])
;
}
public function apply(QueryBuilder $queryBuilder, FilterDataDto $filterDataDto, ?FieldDto $fieldDto, EntityDto $entityDto): void
{
if ($filterDataDto->getValue() == 1)
{
$queryBuilder->andWhere("entity.checker is NOT NULL");
}
if ($filterDataDto->getValue() == 2)
{
$queryBuilder->andWhere("entity.cleaner is NOT NULL");
}
}
}
Error screen

I'm not sure if the attribute comparison could be a nullable value on FilterDataDto. The filter system is normalized on form data. I let others to reply about it.
Right now, I suggest you to rewrite your choice filter from the EA one by using the provided ChoiceFilterType, and adapt keys of form options (minor changes):
//...
final class SupplierFilter implements FilterInterface
{
use FilterTrait;
public static function new(string $propertyName, $label = null): self
{
return (new self())
->setFilterFqcn(__CLASS__)
->setProperty($propertyName)
->setLabel($label)
->setFormType(ChoiceFilterType::class) // EA custom choice filter type
->setFormTypeOption('value_type_options.choices', [/* your choices */])
->setFormTypeOption('value_type_options.multiple', true)
->setFormTypeOption('value_type_options.expanded', true)
// Some other options prefixed by 'value_type_options.' for Symfony ChoiceType options...
;
}
public function apply(QueryBuilder $queryBuilder, FilterDataDto $filterDataDto, ?FieldDto $fieldDto, EntityDto $entityDto): void
{
// Your logic...
}
}
The only (small) risk is in case of EA changes about ChoiceFilterType.
@Ang3 Unfortunately, I don't want the comparison field

Your solution is the same that using directly the ChoiceFilterType with parameters :
public function configureFilters(Filters $filters): Filters
{
return $filters
->add(ChoiceFilter::new('Supplier')->setChoices(["Checker" => 1, "Cleaner" => 2])->canSelectMultiple()->renderExpanded())
//->add(SupplierFilter::new('Supplier'))
;
}
@javiereguiluz I think the attribute comparison may (should ?) be a nullable value on FilterDataDto because most of the time, we do not neek to have the comparaison field.
Is there a workaround, an hidden option, to disable the comparison field ?
Thanks,
@fdiedler, Ok I didn't understand well your needs. In this case, maybe you could try this (on basic ChoiceFilterType):
// ...
->setFormTypeOption('comparison_type', 'hidden') // EA is waiting for a type for the comparaison form
// By setting "hidden", you should have a HiddenType (so hidden input => yes it's a trick! ^^)
@Ang3 Not working, I have an error messsage
Could not load type "hidden": class does not exist.
And if I do setFormTypeOption('comparison_type', 'Symfony\\Component\\Form\\Extension\\Core\\Type\\HiddenType')
An error has occurred resolving the options of the form "Symfony\Component\Form\Extension\Core\Type\HiddenType": The option "type" does not exist.
I just want to have a multiple choice filter like the Symfony ChoiceType field component :) (note that there is no comparison field in Symfony, I don't unterstand the purpose of such this field)
Thanks,
@fdiedler thank you for your feedback. I think I did a mistake on form type option key:
// ...
->setFormTypeOption('comparison_type_options.type', 'hidden') // EA is waiting for a type for the comparaison form
// By setting "hidden", you should have a HiddenType (so hidden input => yes it's a trick! ^^)
If you get an error because comparison is required and not defined somewhere, try to set comparison_type_options.empty_data to true:
// ...
->setFormTypeOption('comparison_type_options.type', 'hidden')
->setFormTypeOption('comparison_type_options.empty_data', true)
@Ang3 Not working
An error has occurred resolving the options of the form "EasyCorp\Bundle\EasyAdminBundle\Form\Type\ComparisonType": The option "type" with value "hidden" is invalid. Accepted values are: "array", "datetime", "choice", "entity", "numeric", "text".
:(
@fdiedler /cc @Ang3
Following code works well for me :+1:
use EasyCorp\Bundle\EasyAdminBundle\Form\Filter\Type\ChoiceFilterType;
use EasyCorp\Bundle\EasyAdminBundle\Form\Type\ComparisonType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class GenerationFilterType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('comparison', HiddenType::class, [
'data' => ComparisonType::CONTAINS,
])
;
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'value_type' => ChoiceType::class,
'value_type_options' => [
'choices' => [
'Choice1' => 1,
'Choice2' => 2,
'Choice3' => 3,
],
'multiple' => true,
'row_attr' => [
'style' => 'margin-top: -12px;', // just to eliminate the ugly margin
],
],
]);
}
public function getParent(): string
{
return ChoiceFilterType::class;
}
}
Why this works
ComparisonFilterType, which is the parent of ChoiceFilterType, adds 'comparison' field as $options['comparison_type'] with $options['comparison_type_options']. So we can simply overwrite this adding.
@ttskch Thanks a lot for your workaround ! :)
@fdiedler /cc @Ang3
Following code works well for me 👍
use EasyCorp\Bundle\EasyAdminBundle\Form\Filter\Type\ChoiceFilterType; use EasyCorp\Bundle\EasyAdminBundle\Form\Type\ComparisonType; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\Extension\Core\Type\HiddenType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; class GenerationFilterType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options): void { $builder ->add('comparison', HiddenType::class, [ 'data' => ComparisonType::CONTAINS, ]) ; } public function configureOptions(OptionsResolver $resolver): void { $resolver->setDefaults([ 'value_type' => ChoiceType::class, 'value_type_options' => [ 'choices' => [ 'Choice1' => 1, 'Choice2' => 2, 'Choice3' => 3, ], 'multiple' => true, 'row_attr' => [ 'style' => 'margin-top: -12px;', // just to eliminate the ugly margin ], ], ]); } public function getParent(): string { return ChoiceFilterType::class; } }![]()
Why this works
ComparisonFilterType, which is the parent ofChoiceFilterType, adds'comparison'field as$options['comparison_type']with$options['comparison_type_options']. So we can simply overwrite this adding.
Thank you for your workaround. This works perfect for me as well :+1