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.
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);