How to use the CheckboxGroup component?

HI everyone,

How do I set the values of a checkboxgroup without firing the addSelectionListener or addValueChangeListener?

Do I have to keep a reference to the registration and remove it before setting the values?

How to use a binder?

Best regards

Hi,
So there are a few approaches to this that I can think of.

  1. Use valueChangeEvent.isFromClient()
    In most cases, you only care about value changes that are initiated by client, so within a change / selection event you would ignore server initiated changes (such as when you use checkboxGroup.setValue(..) or checkboxGroup.select(..))
checkboxGroup.addValueChangeListener(event -> {
    if (event.isFromClient()) { // Client initiated change
        // Do your thing
    }
});
// ... later
checkboxGroup.select("2"); // event.isFromClient() will be false. 
  1. Register the value change listener after value is set.
    If you have the initial value available when creating the checkbox group, you can first make a selection / set value, and only then add a listener, so that the listener is not triggered with the initial value.
var checkboxGroup = new CheckboxGroup<String>();
checkboxGroup.setLabel("Checkbox");
checkboxGroup.setItems("1", "2", "3");
checkboxGroup.select("1"); // initial value, does not trigger value change
checkboxGroup.addValueChangeListener(event -> {
        // Do your thing
});
  1. Have a class variable, that controls whether change listener code executes
    class variable:
private boolean checkboxGroupInitialized = false;
var checkboxGroup = new CheckboxGroup<String>();
checkboxGroup.setLabel("Checkbox");
checkboxGroup.setItems("1", "2", "3");
checkboxGroup.addValueChangeListener(event -> {
    if (checkboxGroupInitialized) {
        // Do your thing
    }
});
// ... later
checkboxGroup.select("1"); // initial selection ignored.
checkboxGroupInitialized = true;

For binding I recommend you read our documentation entry.

Hello Markuns,

thanks for your reply.

Is there any reasons why you didnt mention storing a reference to the registration?

Registration registration = checkboxGroup.addSelectionListener(e → {…

and later one remove it before setting the values again like this: registration.remove();

I think option 1. does not work with karibu, but I am not sure.

It’s a bit more messier in my opinion than the other options, since you have to have the listener code separated from the rest if the CheckboxGroup creation code.
Option number 3 is fairly similar to that approach, but will allow the value change code to stay close to initialization code.
So whenever you would want to update the selection, you would:

private boolean checkboxGroupIgnore = false; 
// later
checkboxGroupInitialized = true;
checkboxGroup.select("1"); 
checkboxGroupInitialized = false;

I think you’re right about Karibu, there might be a workaround. I think in the past I mocked a select event, with isFromClient = true, and then fired it trough the component. But it has been a while, not 100% sure about it.
UI Unit Tests (from Vaadin 24.8.1 / Vaadin 24.7.8) had a fix for this with the test(textField).setValue("New value") that will result in isFromClient = true. UI Unit testing is a commercial feature, so if you have a commercial license, you might prefer that, since its directly inspired by Karibu.