Description
Symfony version(s) affected: 4.4.21
Description
When you add a new form field with the builder, the ChoiceType has an option "multiple".
If you set this option to true, the widget is rendered as select with multiple attribute or checkboxes. You have another option here
error_message. This option is used to populate an error in the form with the provided string template, if something is wrong with the choice. The problem is, this is not working when multiple is set to true.
This is the code snippet where messageTemplate is hardcoded
if ($options['multiple']) {
$builder->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event) use (&$unknownValues) {
// Throw exception if unknown values were submitted
if (\count($unknownValues) > 0) {
$form = $event->getForm();
$clientDataAsString = is_scalar($form->getViewData()) ? (string) $form->getViewData() : \gettype($form->getViewData());
$messageTemplate = 'The value {{ value }} is not valid.';
if (null !== $this->translator) {
$message = $this->translator->trans($messageTemplate, ['{{ value }}' => $clientDataAsString], 'validators');
} else {
$message = strtr($messageTemplate, ['{{ value }}' => $clientDataAsString]);
}
$form->addError(new FormError($message, $messageTemplate, ['{{ value }}' => $clientDataAsString], null, new TransformationFailedException(sprintf('The choices "%s" do not exist in the choice list.', implode('", "', array_keys($unknownValues))))));
}
});
// <select> tag with "multiple" option or list of checkbox inputs
$builder->addViewTransformer(new ChoicesToValuesTransformer($choiceList));
} else {
// <select> tag without "multiple" option or list of radio inputs
$builder->addViewTransformer(new ChoiceToValueTransformer($choiceList));
}
In the newer versions of Symfony like 5.4.* this is fixed by replacing the messageTemplate with the option error_message if it is provided
if ($options['multiple']) {
$messageTemplate = $options['invalid_message'] ?? 'The value {{ value }} is not valid.';
$builder->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event) use (&$unknownValues, $messageTemplate) {
// Throw exception if unknown values were submitted
if (\count($unknownValues) > 0) {
$form = $event->getForm();
$clientDataAsString = is_scalar($form->getViewData()) ? (string) $form->getViewData() : (\is_array($form->getViewData()) ? implode('", "', array_keys($unknownValues)) : \gettype($form->getViewData()));
if (null !== $this->translator) {
$message = $this->translator->trans($messageTemplate, ['{{ value }}' => $clientDataAsString], 'validators');
} else {
$message = strtr($messageTemplate, ['{{ value }}' => $clientDataAsString]);
}
$form->addError(new FormError($message, $messageTemplate, ['{{ value }}' => $clientDataAsString], null, new TransformationFailedException(sprintf('The choices "%s" do not exist in the choice list.', $clientDataAsString))));
}
});
// <select> tag with "multiple" option or list of checkbox inputs
$builder->addViewTransformer(new ChoicesToValuesTransformer($choiceList));
} else {
// <select> tag without "multiple" option or list of radio inputs
$builder->addViewTransformer(new ChoiceToValueTransformer($choiceList));
}
How to reproduce
Create a new form. Add new ChoiceType with the option multiple set to true. Add your desired error_message.
Open the form in the browser and manually manipulate the value of one of the choices. Select that choice and submit the form.
You will get "The value array is not valid" and not your desired message.
Possible Solution
Find the commit where
$messageTemplate = $options['invalid_message'] ?? 'The value {{ value }} is not valid.';
was added and merge it back to LTS version.
Additional context
I know this is a rare bug and someone should manually play with the form, but imagine that this is an API and someone is sending you wrong data. You are presenting him with the message
'The value {{ value }} is not valid.'
Not very helpful