Question

Using FieldGroup, I have a form binding all the properties of Customer using BeanItem<Customer> and displaying them in a FormLayout.

My Customer class is something like:

@Entity
@Table(name="customer")
public class Customer implements Serializable {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private int id;

    private String description;
    (... other fields ...)

    private String language;
    (... getters and setters ...)
}

The property language is a shortcut for the language. For example "de", "en", "fr" and so on.

Furthermore, there's a POJO class named Language (code simplified)

public class Language {
    protected String shortCut;

    public Language(String shortCut)
    {
        this.shortCut = shortCut;
    }

    public String getShortcut()
    {
        return this.shortCut;
    }
}

... and a static List of instances (code simplified):

public static List<Language> LANGUAGES = new ArrayList<>(Arrays.asList(new Language[]{
    new Language("de"),
    new Language("fr"),
    new Language("en")
}));

Along with the customer data in the form layout, I add another combo box containing the above list of languages.

What I want to achieve is, that upon form submit, the language chosen in the combobox is taken and its shortcut written into the BeanItem. pseudo-code:

// Assuming we have a combobox and our customer bean, both created before and elsewhere:
ComboBox cmbLanguage;
BeanItem<Customer> customer;

// Then, the language chosen by the user is:
Language lang = (Language)cmbLanguage.getValue();

// So this should actually happen upon saving the form:
customer.getItemProperty("language").setValue(lang.getShortcut());

I know it would be possible to manually change the customer bean object using a commit handler on the field group. But I would like to avoid this.

Is there a way doing it "automatically" implementing a converter or the like on the combo box, the form or the bean item?

After taking a look at N. Frankel's presentation "Vaadin 7 FieldGroup & Converter" (pages 18 thru 21), I tried with a custom instance of Converter. But this can obviously not work because the bound property cannot be both, the set/list of languages and the customers language.

How to achieve this?

Note: due to interoperability, I can not change Customer and I need to use the construct with the language class.

Was it helpful?

Solution

If you need ComboBox that give you as a value Language you could extend ComboBox class:

class LanguageComboBox extends ComboBox {
    public LanguageComboBox(String caption, Collection<Language> languages) {
        super(caption, getShortcuts(languages));
    }

    @Override
    public Language getValue() {
       return new Language((String) super.getValue());
    }

    private static List<String> getShortcuts(Collection<Language> languages) {
       // extract shortcuts using java 1.8 
       return languages.stream()
            .map(language -> language.getShortcut())
            .collect(Collectors.toList());
    }
}

and then you can easily add this to FieldGroup with BeanItem<Customer>:

    ComboBox comboBox = new LanguageComboBox("Language", LANGUAGES);
    fieldGroup.bind(comboBox,"language");

After submit your customer will have the proper value of language.

In my opinion you shouldn't use entities on the view - as you mentioned you cannot change Customer object and probably this class contains much more fields that you need to your view. I would rather create separate POJO class to this view - this give you much more flexibility and there will be no such problems like you reported. Of course on the end you need to convert your view object to entity or even more entities but in most cases it is worth to bear that cost.

OTHER TIPS

You could add the shortcut value as THE value to the ComboBox and define an optional caption:

    cmbx.addContainerProperty("caption", String.class, "");
    cmbx.setItemCaptionPropertyId("caption");

    cmbx.addItem(languageEN.getLanguageShortCut()).getItemProperty("caption").setValue(languageEN.getLanguageLong());
    cmbx.addItem(languageFR.getLanguageShortCut()).getItemProperty("caption").setValue(languageFR.getLanguageLong());
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top