`setValue` method in `RadioButtonGroup` incorrectly deselects all options when null is passed
Description
In the RadioButtonGroup component, the setValue method deselects all options when null is passed as the value. This behavior is not always desirable, as null might represent a valid state that should be selectable rather than deselecting all options.
Expected outcome
When null is passed to the setValue method, the RadioButtonGroup should allow for custom handling of this value, rather than automatically deselecting all options. This would enable null to be represented meaningfully within the selection.
OR:
Make the RadioButton class public so that the method can be overridden with some workaround using inheritance. https://github.com/vaadin/flow-components/issues/1952
Minimal reproducible example
RadioButtonGroup<Boolean> radioButtonGroup = new RadioButtonGroup<>(); radioButtonGroup.setItems(true, false, null); radioButtonGroup.setValue(null);
Steps to reproduce
- Create a RadioButtonGroup<Boolean> and add the values true, false, and null (e.g. null for "not specified").
- Set the initial value of the RadioButtonGroup to null.
- Observe how the selection in the RadioButtonGroup behaves, particularly when null is set as the value.
Environment
Vaadin version(s): 24.4.4 OS: Windows
Browsers
Firefox, Edge
@knoobie May I ask why you gave it a thumbs down? Do you think that it should not be possible to select null in a radio button group?
The only other way I can think of to select no option is to click on the selected option again. However, this is not intuitive to all users, and it is also not visible whether it is possible to select null or not.
null / emptyValue has a special meaning for all fields - changing it just for radio buttons is not good practice overall. Addittionally the native type=radio does not support it either, once a value is selected it stays selected - that's common UX for over two decades and native behavior. If you need the possibility to reset the value or frankly saying: you need a default. This is normally done by adding a "Default" option to your RadioButtonGroup so that the user can select it and no, null is not an option.
Thanks @knoobie for explaining this. I don't have much to add, and IMO we should consider this issue a won't fix.
Also, please note that the vaadin-radio-group web component generally expects a string value, not boolean.
I totally agree that unselecting a single radio button is a unintuitive behavior. What is the alternative for Booleans though? Is it to
- either not use radio button group at all for Booleans (Whats the alternative?)
- or to always convert Booleans zu String (just to convert it with TextRenderer again for internationalisation)
Especially for questionairs, it is very common to use a radio button group to choose between "yes", "no", and "no answer". Always converting to String feels like a dirty hack for me.
@Getter
@AllArgsConstructor
enum YesNoNope {
YES(true),
NO(false),
NOPE(null);
private final Boolean value;
}
Ideally you'll want a properly typed data structure that expresses intent, rather than having a null value that, as seen in this issue, could mean many things. For example an enum where one of the values is "no answer". If your data is dynamic it's a bit more effort, but still doable by having a wrapper class where an instance knows whether it is the "no answer" or not.
The use case with "no selection" applies to all kind of data types, not only to Booleans or enums. What you suggest is basically that radio button goup can generally only be used with data types that employ the null object pattern. At least according to my experience, it is often simply not practical to use the pattern. Additionally, the data type is often determined by the domain model. Creating a wrapper type for all types that are used by domain model would be not only tedious, but also difficult to maintain. "A bit more effort" is such an understatement.
What I did now as a workaround is to wrap everything in a Optional in a converter for radio button groups, and change all text renders accordingly.... This does not feel like "the intended good way" at all... (Thanks for the idea for that still, having a workaround is better than not having one)
For now this is the intended behavior, however it should be documented in the JavaDoc of RadioButtonGroup.setValue.