I have been studying Vaadin for some months and now I have faced up with the problem I didn’t manage to resolve by myself.
I would like to implement an option of adding new values to a combobox. The combobox includes the names of the operating systems, for example.
Here is a fragment of my code.
I have a bean which presents an operating system:
public class OperatingSystem implements Serializable {
private static final long serialVersionUID = 1L;
private Integer osId;
private String osName;
public OperationSystem(Integer osId, String osName) {
this.osId = osId;
this.osName = osName;
}
public Integer getOsId() {
return osId;
}
public void setOsId(Integer osId) {
this.osId = osId;
}
public String getOsName() {
return osName;
}
public void setOsName(String osName) {
this.osName = osName;
}
}
Also a class that generates test data:
[code]
public class TestData {
public static ArrayList<OperationSystem> getOperatingSystems() {
ArrayList<OperationSystem> os = new ArrayList<>();
os.add(new OperationSystem(1, "Linux"));
os.add(new OperationSystem(2, "Windows"));
os.add(new OperationSystem(3, "FreeBSD"));
return os;
}
}
[/code]And a code that creates and handles the combobox:
BeanContainer<Integer, OperatingSystem> os = new BeanContainer<>(OperatingSystem.class);
os.setBeanIdProperty("osId");
ArrayList<OperatingSystem> osData = TestData.getOperatingSystems();
os.addAll(osData);
ComboBox osName = new ComboBox("Select OS Name:", os);
osName.setNullSelectionAllowed(true);
osName.setItemCaptionPropertyId("osName");
osName.setNewItemsAllowed(true);
osName.setNewItemHandler(newItemCaption -> {
boolean newItem = osData.stream().noneMatch(data -> data.getOsName().equalsIgnoreCase(newItemCaption));
if (newItem) {
OperatingSystem newOs = new OperatingSystem(generateNextOsId(osData), newItemCaption);
os.addBean(newOs);
// osData.add(newOs); // if remove comment everything is fine
osName.select(newOs.getOsId());
}
});
Please also pay attention that a method generateNextOsId was created for generation of next id for an operating system.
private Integer generateNextOsId(final ArrayList<OperatingSystem> osData) {
Integer currentMaxOsId = osData.stream().mapToInt(OperatingSystem::getOsId).max().getAsInt();
return new Integer(currentMaxOsId.intValue() + 1);
}
And it works, but don’t in a right way
What do I mean?
Let suppose, that I want to add, says, UNIX operating system into created combobox. I will be succeed in this action. The generateNextOsId method will create new id with value equals 4 (four) and UNIX operating system will be succesfully added into the bean container (is represented by a variable named “os”) and will appear in the combobox and combobox drop-down list. OK.
Go further.
Next, I have an strong desire to add Xenix operating system (oh, Lord) into the combobox. That is impossible and I know why. It’s becouse of generateNextOsId method will create new id with value equals 4 (four) AGAIN!!! It means that changes from the bean container don’t propagated to the backing beans (is represented by a variable named “osData”) .
Probably that’s right behaviour.
If I remove comment imposed on line marked by “if remove comment everything is fine” - it works and I can add whole bunch of the new operating systems into combobox!
I have put through myself some information about containers but it seems it’s not enough becouse I’m stuck.
So final question is very simple: what is the right solution to get data propagated from the bean container to the backing beans? It doesn’t seem right for me to use add methods twice:
os.addBean(newOs);
osData.add(newOs);
I would appreciate you if you show me more elegant and (the main thing!) right solution from Vaadin’s point of view.