javabindingvaadinvaadin-flowincompatibility

Vaadin Binder for MultiSelectComboBox



Can somebody please help me with Vaadin Binder for this `MultiSelectComboBox`.
Does the MultiSelectComboBox component, always requires a `Set` for the binding methods ?

I have such entity

@Entity(name = "recipes")
public class Recipe {

    // ...

    @Getter
    @Setter
    private List<Category> categories;

    // ...
}

My implementation of Binder for MultiSelectComboBox

private final Binder<Recipe> binder = new Binder<>(Recipe.class);
private final MultiSelectComboBox<Category> categoryMultiselect = new MultiSelectComboBox<>("Categories");

// ...

private void initBinder() {
    binder.forField(categoryMultiselect)
            .asRequired("Please fill this field")
            .withValidator(s -> !s.isEmpty(), "Please select at least one category")
            .withValidator(s -> s.size() <= 5, "Please select up to 5 categories")
            .bind(Recipe::getCategories, Recipe::setCategories);
}

Throws Incompatible types: Set<Category> is not convertible to List<Category>, as MultiSelectComboBox returns a Set and Recipe::getCategories returns a List<Category>.

Any ideas how can be this avoided ?
PS: I don't really want to change the List<Category> to Set<Category> in my Recipe.class.


Solution

  • You can convert Set to list using withConverter.

    private void initBinder() {
    Converter<Set<Category>, List<Category>> setToListConverter = new Converter<Set<Category>, List<Category>>() {
        @Override
        public Result<List<Category>> convertToModel(Set<Category> set, ValueContext context) {
            List<Category> list = new ArrayList<>(set);
            return Result.ok(list);
        }
    
        @Override
        public Set<Category> convertToPresentation(List<Category> list, ValueContext context) {
            Set<Category> set = new HashSet<>(list);
            return set;
        }
    };
    
    binder.forField(categoryMultiselect)
            .asRequired("Please fill this field")
            .withValidator(s -> !s.isEmpty(), "Please select at least one category")
            .withValidator(s -> s.size() <= 5, "Please select up to 5 categories")
            .withConverter(setToListConverter)
            .bind(Recipe::getCategories, Recipe::setCategories);}
    

    (https://vaadin.com/docs/v23/binding-data/components-binder-validation#converting-user-input)