Vaadin ComboBox: Конвертиране между String и POJO

Използвайки FieldGroup, имам формуляр, обвързващ всички свойства на Customer с помощта на BeanItem<Customer> и показващ ги в FormLayout.

Моят Customer клас е нещо като:

@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 ...)
}

Свойството language е пряк път за езика. Например "de", "en", "fr" и така нататък.

Освен това има POJO клас с име Language (кодът е опростен)

public class Language {
    protected String shortCut;

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

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

... и статичен списък с екземпляри (опростен код):

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

Заедно с клиентските данни в оформлението на формуляра, добавям още едно комбинирано поле, съдържащо горния списък с езици.

Това, което искам да постигна, е, че при изпращане на формуляр езикът, избран в падащото поле, се взема и неговият пряк път се записва в BeanItem. псевдокод:

// 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());

Знам, че би било възможно ръчно да промените клиентския bean обект, като използвате манипулатор на ангажименти в групата полета. Но бих искал да избегна това.

Има ли начин да го направите "автоматично" чрез внедряване на конвертор или нещо подобно в комбинираното поле, формуляра или елемента bean?

След като разгледахте N. Презентацията на Frankel „Vaadin 7 FieldGroup & Converter“ (страници 18 до 21), опитах с потребителски екземпляр на Converter. Но това очевидно не може да работи, защото обвързаното свойство не може да бъде и двете, наборът/списъкът от езици и езикът на клиента.

Как да постигнете това?

Забележка: поради оперативна съвместимост не мога да променя Customer и трябва да използвам конструкцията с езиковия клас.


person Atmocreations    schedule 08.05.2014    source източник
comment
Бихте ли изяснили въпроса си? От описанието не става ясно какво се опитвате да направите и защо имате нужда от Convener, ако просто се опитвате да свържете комбинираното поле и полето в обекта.   -  person user3551612    schedule 08.05.2014
comment
промени въпроса ми. Надявам се, че сега е много по-ясно.   -  person Atmocreations    schedule 08.05.2014


Отговори (2)


Ако имате нужда от ComboBox, който ви дава като стойност Language, можете да разширите класа ComboBox:

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());
    }
}

и след това можете лесно да добавите това към FieldGroup с BeanItem<Customer>:

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

След изпращане вашият клиент ще има правилната стойност на езика.

Според мен не трябва да използвате обекти в изгледа - както споменахте, не можете да промените Customer обект и вероятно този клас съдържа много повече полета, които са ви необходими за вашия изглед. Бих предпочел да създам отделен POJO клас за този изглед - това ви дава много повече гъвкавост и няма да има такива проблеми, каквито съобщихте. Разбира се, в края на краищата трябва да преобразувате вашия изглед обект в обект или дори повече обекти, но в повечето случаи си струва да поемете тази цена.

person Arek Trzepacz    schedule 10.05.2014

Можете да добавите стойността на прекия път като стойността към ComboBox и да дефинирате незадължителен надпис:

    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());
person nexus    schedule 08.05.2014