Hi, I have a ComboBox which presents a list of possible dates to execute a project planning. There’s a BeamItemContainer of LocalDate objects attached to the ComboBox using setContainerDataSource.
It all works well but the LocalDate presentation is using the “yyyy-MM-ddd” format and I need it to be shown as “ddd/MM/yyyy”.
I tried to create a converter but had no success whatsoever. Can you please tell me what I’m doing wrong?
List<LocalDate> availableDates = new ArrayList<LocalDate>(projectPlanningWrapper.getPossibleDatesToPlan());
BeanItemContainer<LocalDate> container = new BeanItemContainer<LocalDate>(LocalDate.class);
Collections.sort(availableDates);
container.addAll(availableDates);
possibleDatesToPlan.setContainerDataSource(container)
possibleDatesToPlan.setConverter(new Converter() {
private static final long serialVersionUID = 1L;
@Override
public Object convertToModel(Object value, Class targetType, Locale locale) throws ConversionException {
if(value == null) {
return null;
} else{
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
return LocalDate.parse((String) value, formatter);
}
}
@Override
public Object convertToPresentation(Object value, Class targetType, Locale locale) throws ConversionException {
if (value == null){
return null;
}
else{
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
return ((LocalDate) value).format(formatter);
}
}
@Override
public Class getModelType() {
return LocalDate.class;
}
@Override
public Class getPresentationType() {
return String.class;
}
});
you can set the captions of individual items by comboBox.setItemCaption(itemId, caption), which might be enough for your needs. If you need the same conversion in many places, one possible solution would be to create a new ConverterFactory for the session, which would look like something like the following:
public class StringToLocalDateConverter implements Converter<String, LocalDate> {
@Override
public LocalDate convertToModel(String value, Class<? extends LocalDate> targetType, Locale locale)
throws com.vaadin.data.util.converter.Converter.ConversionException {
if(value == null) {
return null;
} else{
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
return LocalDate.parse((String) value, formatter);
}
}
@Override
public String convertToPresentation(LocalDate value, Class<? extends String> targetType, Locale locale)
throws com.vaadin.data.util.converter.Converter.ConversionException {
if (value == null){
return null;
}
else{
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
return ((LocalDate) value).format(formatter);
}
}
@Override
public Class<LocalDate> getModelType() {
return LocalDate.class;
}
@Override
public Class<String> getPresentationType() {
return String.class;
}
}
public class MyConverterFactory extends DefaultConverterFactory {
@Override
protected <PRESENTATION, MODEL> Converter<PRESENTATION, MODEL> findConverter(
Class<PRESENTATION> presentationType, Class<MODEL> modelType) {
// Your specific localDate converter
if (presentationType == String.class && modelType == LocalDate.class) {
return (Converter<PRESENTATION, MODEL>) new StringToLocalDateConverter();
}
// Fall back to default in other cases
return super.findConverter(presentationType, modelType);
}
}
private void createComboBox(VerticalLayout layout) {
VaadinSession.getCurrent().setConverterFactory(new MyConverterFactory());
LocalDate ld = LocalDate.now();
LocalDate ld2 = ld.plusDays(3);
List<LocalDate> list = new ArrayList<>();
list.add(ld);
list.add(ld2);
BeanItemContainer<LocalDate> bic = new BeanItemContainer<>(LocalDate.class, list);
ComboBox cb = new ComboBox();
cb.setContainerDataSource(bic);
layout.addComponent(cb);
}
In the end I decided to create a method that converts from LocalDate to Date and another one to do the other way. Still, it seems like a terrible solution to convert every value before I put it inside the comboBox and then convert it back when the user choose one (I have to use it in a filter). But I’ll have to stay with that for a while.