Problem/Motivation
Current Behavior:
When building custom form with #radios only #attributes are passed to the individual #radio elements. We can still access the CvValidator 'required' by setting #attributes => ['required' => ''] however the error message will still appear next to the first radio in the set and display a misleading message like '{Option Label} is required'.
Expected Behavior:
When building custom form with #radios I can use #required and #required_error and the radio children will inherit the validator criteria. When submitting a form with a type #radios without selecting a radio, I expect the configured #required_error to appear beneath the of the wrapping fieldset like IFE.
Proposed resolution
Optional:
Leverage patch on https://www.drupal.org/project/drupal/issues/2951317 to allow #required to be passed to radio elements.
If you don't use the above patch, the CvValidator required plugin can still be triggered on radio via "#attributes => ['required' => ' ']"
For passing #required_error to radio elements:
Add conditional to Required.php that checks for #type => radio. If radio is not required and has parent #radios, run getRules on the parent, so we can access the #required_error.
To alter position of radios error message:
Add errorPlacement callback to cv.jquery.ife.js and insert beneath of the closest fieldset with data-drupal-selector that matches the errored radios data-drupal-selector without its radio index.
Remaining tasks
Add the patch.
API changes
// With a patch from https://www.drupal.org/project/drupal/issues/2951317
$form['radios'] = [
'#type' => 'radios',
'#title' => $this->t('How many Drupal sites have you built?'),
'#options' => $options_array,
'#required' => TRUE,
'#required_error' => 'Custom message',
];
// Without patch from https://www.drupal.org/project/drupal/issues/2951317.
$form['radios'] = [
'#type' => 'radios',
'#title' => $this->t('How many Drupal sites have you built?'),
'#options' => $options_array,
'#required' => TRUE, // continue to include so fieldset is rendered as required.
'#attributes' => [
'required' => ' ', // passed to #radio elements and caught by Required validator plugin.
],
'#required_error' => 'Custom message',
];
| Comment | File | Size | Author |
|---|---|---|---|
| #12 | interdiff_8-12.txt | 533 bytes | pakmanlh |
| #12 | 3166606-12.patch | 1.95 KB | pakmanlh |
| #8 | 3166606-8.patch | 1.81 KB | themodularlab |
| #5 | 3166606-5.patch | 2.09 KB | butlerbryanc |
Comments
Comment #2
butlerbryanc commentedComment #3
butlerbryanc commentedComment #4
butlerbryanc commentedComment #5
butlerbryanc commentedUpdate
Added isset check for #type before checking for radio to prevent errors when #type isn't set.
Comment #6
butlerbryanc commentedComment #7
nikunjkotecha@butlerbryanc
Thanks for providing all the details in issue description and also for the patch.
Can you please add test for this?
Comment #8
themodularlabI found that 3166606-5.patch didn't solve my issue at all. When i have a field set of multiple checkboxes and/or radios, the error message is still getting applied to the first radio/checkbox element and breaking the layout. So I made some minor adjustments. Possibly not the direction you want to take this, more might need more work, but it's at least a starting point or an alternative.
Comment #9
fenstratJust a heads up that if this is affecting you with webforms there is the webform_clientside_validation module (part of webform) that should fix this.
Comment #10
trevorbradley commented@fenstrat just a heads up that webform_clientside_validation actually requires drupal/clientside_validation as a dependency in its info.yml file.
Something not note working with patch #8. Even with the patch applied, my validation message appears between the first radio button and the label. Investigating.
Comment #11
dystopianblue commentedConfirmed, #8 works. Make sure to enable `inline_form_errors` which I had forgot to do, causing it not to work initially.
Comment #12
pakmanlhI can confirm #8 works but sometimes the assumption of $complete_form['#type'] always existing can generate warning messages, for instance when you access `/admin/config/regional/language`when you have language module active.
I just added a check to mitigate this situation. Thanks!
Comment #13
andre.bononHi, thanks everyone for your contribution to this issue.
I tried to fix the issue using your approach for webforms (clientside_validation + webform_clientside_validation + inline_form_errors), but the issue was still happening.
In my case, my theme extends from stable9 that doesn't add classes like "form-checkboxes", "form-radios", or "form-type-[type]" to the form elements, which are used in the webform_clientside_validation js selectors.
Stable9 adds "js-form-type-[type]" and forgets about the "form-type-[type]" as in the snippet below:
I fixed the placement issue by overriding the form-element.html.twig and adding the code above. For the fieldset.html.twig, I added the following:
Comment #14
andre.bononI reported this core bug https://www.drupal.org/project/drupal/issues/3380021, so it might avoid issues with themes based on stable9.
Comment #15
andre.bononComment #16
igorbiki commentedSolution/patch #12 works for me. Both radios and checkboxes (as webforms elements) display error messages beneath all options.
Comment #17
nikunjkotechaThanks everyone, I would really appreciate if we can have some tests added to the patch.
I am trying to reproduce and confirm the fix and improve the solution (make it generic and work even without inline_form_errors module), I have got radios working but not able to make normal required validation work for checkboxes.