Handling two ComboBoxes in Vaadin

This post is a solution to a problem I faced developing an application in Vaadin. It is related to handling two ComboBoxes in Vaadin, where the values in the second ComboBox depend on the selection of the first ComboBox

Handling two ComboBoxes in Vaadin

The Vaadin form component is easily handled and rendered with a FormFieldFactory. So I have a Form called MusicForm
import com.vaadin.data.util.BeanItem;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.Form;


/**
* The Class MusicForm.
*/
public class MusicForm extends Form implements Button.ClickListener {

/** Save button for the form. */
private Button btnSave;

/** The class descriptor form field factory. */
private MusicFormFieldFactory mfff;

/** The Constant serialVersionUID. */
private static final long serialVersionUID = 1L;

/**
* Instantiates a new class descriptor form.
*
* @param Music
* the class descriptor
*/
public MusicForm(Music music) {
setWriteThrough(false);
setImmediate(true);
mfff = new MusicFormFieldFactory();
setFormFieldFactory(mfff);
BeanItem itemPropertyDescriptor = new BeanItem(music);
setItemDataSource(itemPropertyDescriptor);
btnSave = new Button("Save");
btnSave.addListener((ClickListener) this);
btnSave.setDisableOnClick(true);

}

/**
* Gets the class descriptor form field factory.
*
* @return the MusicFormFieldFactory
*/
public MusicFormFieldFactory getMusicFormFieldFactory() {
return mfff;
}

/**
* Sets the class descriptor form field factory.
*
* @param MusicFormFieldFactory
* the MusicFormFieldFactory to set
*/
public void setMusicFormFieldFactory(MusicFormFieldFactory musicFormFieldFactory) {
this.mfff = musicFormFieldFactory;
}

}
Here is the FormFieldFactory code:
import java.util.Collection;
import com.connectfront.workbench.Workbench;
import com.vaadin.data.Item;
import com.vaadin.data.Property;
import com.vaadin.data.Validator;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.util.BeanItem;
import com.vaadin.ui.ComboBox;
import com.vaadin.ui.Component;
import com.vaadin.ui.DefaultFieldFactory;
import com.vaadin.ui.Field;
import com.vaadin.ui.TextField;
import com.vaadin.ui.Tree;

public class MusicFormFieldFactory extends DefaultFieldFactory {

private static final long serialVersionUID = 1L;

public Field createField(Item item, Object propertyId, final Component uiContext) {
String pid = (String) propertyId;
if ("name".equals(pid)) {
final TextField f = (TextField) super.createField(item, propertyId, uiContext);
f.setMaxLength(30);
f.setNullRepresentation("");
f.setRequired(true);
return f;
}
else if ("musicType".equals(pid)) {
ComboBox select = new ComboBox();
boolean setDefault = false;
for (Music m : MusicEnum.values()) {
select.addItem(m.getType());
}
select.setCaption("Music Type");
select.setRequiredError("Please select music type");
select.addListener(new Property.ValueChangeListener() {
private static final long serialVersionUID = -7887302901429982273L;
public void valueChange(ValueChangeEvent event) {
Music musicType = (Music) event.getProperty().getValue();
if (null != musicType) {
ComboBox connectorComboBox = new ComboBox();
for(Song o : Songs.getSongListForMusicType(musicType)){
connectorComboBox.addItem(o);
}
connectorComboBox.setNewItemsAllowed(false);
connectorComboBox.setWidth("80%");
connectorComboBox.setRequired(true);
connectorComboBox.setCaption("Song");
connectorComboBox.setRequiredError("Please select song");
connectorComboBox.requestRepaint();
if (uiContext instanceof MusicForm )
{
((MusicForm) uiContext).addField("song list", connectorComboBox);
}

}
}

});

return select;
}
return null;
}
}
The key here is to add the comboBox as a field in the uiContext which eventually is of type MusicForm. When the user selects a value form the music type comboBox the value change listener is triggered and it adds the sons comboBox in the uiContext at the appropriate position. Hope this helps. Stay connected and stay Subscribed