vaadinvaadin-flowvaadin21

ComboBox in Vaadin 21 shows no Items


I'm trying to use a ComboBox with Vaadin 21. The combo box does not get populated with items, even though I have used different variants of populating. Also the placeholder is not set. The ComboBox remains with a dashed outline (which means disabled, I guess).

public class EventFormLayout extends HorizontalLayout {

    private final EventRepository eventRepository;

    private final ComboBox<String> timezone = new ComboBox<>("Timezone");;

    private Button cancel = new Button("Cancel");
    private Button save = new Button("Save");

    private Binder<Event> binder = new Binder(Event.class);

    @Autowired
    public EventFormLayout(Event event, EventRepository eventRepository) {
        this.eventRepository = eventRepository;

        ListDataProvider<String> tzDataProvider = DataProvider.ofCollection(ZoneId.getAvailableZoneIds());
        timezone.setLabel("Timezone");

        timezone.setItems(tzDataProvider);
        //timezone.setItems(ZoneId.getAvailableZoneIds());
        //timezone.setItems("UTC", "Europe/Berlin", "Europe/Paris");
        timezone.setPlaceholder("Timezone");
        timezone.setReadOnly(false);
        timezone.setEnabled(true);

        add(createTitle());
        add(createFormLayout());
        add(createButtonLayout());

        binder.bindInstanceFields(this);
        clearForm();

        cancel.addClickListener(e -> clearForm());
        save.addClickListener(e -> {
            eventRepository.save(binder.getBean());
            clearForm();
        });
    }

    private void clearForm() {
        binder.setBean(new Event());
    }

    private Component createTitle() {
        return new H3("Event");
    }

    private Component createFormLayout() {
        FormLayout formLayout = new FormLayout();
        formLayout.add(title, text, year, month, day, time, timezone);
        return formLayout;
    }

    private Component createButtonLayout() {
        HorizontalLayout buttonLayout = new HorizontalLayout();
        buttonLayout.addClassName("button-layout");
        save.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
        buttonLayout.add(save);
        buttonLayout.add(cancel);
        return buttonLayout;
    }

}

The entity looks something like this:

@Component
public class Event {

    @Transient @Getter
    private String timezone;

    public String setTimezone(String timezone) {
        this.timezone = timezone;
        return this.timezone;
    }

}

The property is transient, because in my actual class, I do something with the value and save it to another property, but the fact that it is transient has nothing to do with the problem, I've tried it out.


Solution

  • The problem in this case was, that the setter returned something. This broke automatic binding. Now there are two ways to fix it: either make the setter return nothing, or explicitly bind the property,

    binder.forField(timezone).bind(Event::getTimezone, Event::setTimezone);
    // before
    binder.bindInstanceFields(this);