Select component does not emit "blur" events
I am using the Conform library for form management including form validation. My form has been set up with shouldRevalidate: "onBlur", leaving the shouldValidate setting as the default value"onSubmit". These settings mean that on initially filling in a form, validation won't happen until the initial submit attempt, but after that (assuming there were validation errors) when a user moves on from editing a field the form should revalidate, and errors should be cleared.
When using a native select element, after picking an option when the user clicks away a blur event will be emitted, and thus the form will revalidate.
Unfortunately the Radix Themes Select components do not emit blur events. Therefore after an option from a Select has been chosen and the user has moved on to another form field, the validation won't update. This is problematic, as it makes for a poor user experience.
(The only way to persuade the form to revalidate after using a Select component is either to attempt to re-submit it, or to click into and out of a TextField, as that does emit a blur event.)
A very simplistic work-around to this issue is to change my form configuration to use shouldRevalidate: "onInput" which will work as the Select component does emit input events`, however in general re-validating on input tends not to be great for UX or accessibility.
OK - some more information...
on further investigation I found that a blur event does get emitted from the Select component, however the target of this event is the button element used for the trigger.
as the target element for the blur event is not the form field element, i.e. the select that is being used for the value, this isn't picked up by Conform as an event relating to a form change.
I have a work-around to this issue now for my code which is to add an onBlur handler onto the Select.Trigger using the following function:
const handleBlur = (event) => {
const target = event.target;
// the event target will be a "button" when it's equivalent to blurring a select
if (target?.type == "button") {
// Simulate a blur on the corresponding select input
const input = target.parentElement?.querySelector("select");
input?.focus();
input?.blur();
}
};
ideally something similar to this functionality should be built into the Select component to help ensure it works in a manner that is more consistent with the underlying select element.
(Conform recently added an alternative way to integrate with components like Select via a new useControl hook, but using that requires passing a ref from the hook to the underlying select element, which doesn't seem to be possible with the Radix Themes Select component)
The same issue exists for the Checkbox component, and the same workaround can be applied there too