Setting a default value on a ComboBox

How to set the value to show in a ComboBox?

Basically I have a key-value POJO, which have two fields, a key, and a value, then I create a bunch of items into a collection:


	List<KeyValuePojo> pojos = Arrays.asList(
		new KeyValuePojo( "key1", "value1" ),
		new KeyValuePojo( "key2", "value2" ),
		new KeyValuePojo( "key3", "value3" ),
		new KeyValuePojo( "key4", "value4" )
	);

Then I create a ComboBox, and set the pojos collection as DataSource, and forbid null selection because I want the user to choose one from the list.


	ComboBox myCombo = new ComboBox("caption", pojos);
	myCombo.setNullSelectionAllowed(false);

Then I want to choose one by default, lets say the first one.


	Collection<?> itemIds = myCombo.getItemIds();
	Object defaultValue = myCombo.getItem(itemIds.iterator().next());
	myCombo.setValue(defaultValue);

If I ask for the value of myCombo, it returns me the pojo with key=“key1” and value=“value1”, but at the screen I only see a comboBox with nothing selected.

I’ve tried repainting the content, calling the setValue after and before addding it to any layout and i’ve tried too using the method select(Object itemId) instead, but the problem is still there.

does anybody know what’s happening?

The value is the item id, not the item. So

myCombo.setValue(itemIds.iterator().next())

should work

No, the problem is just the same.

I printted the objects returned by getItemIds and all of them are just the objects I inserted into the comboBox as dataSource.

Then I extended ComboBox on a KeyValueComboBox class, and i’m overriding the setValue method doing the following:


public class KeyValueComboBox<K, V> extends ComboBox {
	public KeyValueComboBox(String caption, Map<K,V> keyValueMap) {
		super(caption,  KeyValueComboBox.getPojos(keyValueMap));
		setValue(keyValueMap.keySet().iterator().next());
	}

	private static <K,V> List<KeyValuePojo<K,V>> getPojos(Map<K,V> keyValueMap) {
		List<KeyValuePojo<K,V>> pojos = new ArrayList<KeyValuePojo<K,V>>(keyValueMap.size());
		for (K key : keyValueMap.keySet())
			pojos.add(new KeyValuePojo<K,V>(key, keyValueMap.get(key)));
		return pojos;
	}

	@Override
	public void setValue(Object item) {
		// I expect here item is instance of K
		super.setValue(getItemIdAssociatedTo(item));
	}

	private KeyValuePojo<K,V> getItemIdAssociatedTo(Object key) {
		for (Object pojo :getItemIds()) {
			KeyValuePojo<K,V> casted = (KeyValuePojo<K,V>)pojo;
			if (casted.fKey.equals(key))
				return casted;
		}
		return null;
	}
...

The KeyValuePojo is a private class inside the KeyValueComboBox class, something basically like this:


	private static class KeyValuePojo<K, V> {
		K fKey;
		V fValue;

		public KeyValuePojo(K key, V value) {
			fKey = key;
			fValue = value;
		}
		
		@Override
		public String toString() {
			return fValue.toString();
		}
	}
}

As you can see i’m asking the component for its ids and then choosing one to set as the default value, but isn’t working. I reapeat again that if I use then the method: getValue, it does return me the value i’ve just set, but is not displayed at all.

The problem is not in the logic but in the render.

After several attempts I gave up and used the “other” constructor available for ComboBox. The one that takes a Container as argument instead of Collection.

This way the KeyValueComboBox is something like this:


public class KeyValueComboBox<K, V> extends ComboBox {

	public KeyValueComboBox(final String caption, final Map<K, V> keyValueMap, final Class<K> keyClass, final Class<V> valueClass) {
		super(caption, new KeyValueContainer<K, V>(keyValueMap, keyClass, valueClass));
	}

	private static class KeyValueContainer<K, V> extends IndexedContainer {
		public enum PropertyName {
			KEY,
			VALUE
		}

		public KeyValueContainer(final Map<K, V> keyValueMap, final Class<K> keyClass, final Class<V> valueClass) {
			addContainerProperty(PropertyName.KEY, keyClass, null);
			addContainerProperty(PropertyName.VALUE, valueClass, null);

			for (final K key: keyValueMap.keySet()) {
				final V value = keyValueMap.get(key);
				final Item item = addItem(value.toString()); //Be careful with null values
				item.getItemProperty(PropertyName.KEY).setValue(key);
				item.getItemProperty(PropertyName.VALUE).setValue(value);
			}
		}
	}

...
}

And override the method setValue with something like this:


	@Override
	public void setValue(final Object key) {
		super.setValue(fKeyValueMap.get(key).toString());
	}

This way, we are working with Strings as ids (which is the way the ComboBox works fine) and add the key and the value as extra properties.

Just for the sake of it, I tested this code:

        List<KeyValuePojo> pojos = Arrays.asList(
                new KeyValuePojo("key1", "value1"), 
                new KeyValuePojo("key2", "value2"),
                new KeyValuePojo("key3", "value3"), 
                new KeyValuePojo("key4", "value4"));

        ComboBox combo = new ComboBox("caption", pojos);
        combo.setNullSelectionAllowed(false);
        Collection<?> itemIds = combo.getItemIds();
        combo.setValue(itemIds.iterator().next());

With this pojo:

    class KeyValuePojo {
        private Object key;
        private Object value;

        public KeyValuePojo(Object key, Object value) {
            setKey(key);
            setValue(value);
        }

        public void setKey(Object key) {
            this.key = key;
        }

        public Object getKey() {
            return key;
        }

        public void setValue(Object value) {
            this.value = value;
        }

        public Object getValue() {
            return value;
        }

    }

And it worked fine, with the result of Object.toString() rendered on the ComboBox items. :slight_smile:

I tried with
Opzione opt = (Opzione)xpComponent;
Object id = combo.addItem(opt);
if(opt.isSelected()) {
combo.setValue(id);
}
where Opzione is my pojo.
I’ve only one Opzione with selected = true but I don’t see it as value in the combo : it’s still blank with no initial selected value.
What’s wrong ?
Tks
Tullio

My first guess is that your class Opzione has an equals() or hashCode() method implemented so, that setValue() does not find it.

You could also check with combo.getValue() whether the value has been correctly set on the server side. If it is set on the server, equals() works but either you are changing the value when you shouldn’t (e.g. the paint phase or in a background thread) or there might be a bug in ComboBox.

I’ve no equals nor hashCode methods in my Opzione class, only a toString method.
Could toString create the problem ?
I created an equals method in my Opzione class but I don’t get an Opzione as input but a IndexedContainer$IndexedContainerItem class.
What’s wrong ?
Tks
Tullio

Note to self: read the code more carefully before replying…

When you use the addItem(Object id) version, it does return the created item, not its id. The version addItem(), on the other hand, returns the identifier of the item it has created.

Use opt as the id.

I already tried to do that but I got another error and I thought it was not the correct idea.
The error is
com.vaadin.event.ListenerMethod$MethodException
Cause: java.lang.ClassCastException: axioma.rubik.engine.vaadin.node.Opzione cannot be cast to java.lang.String
at com.vaadin.event.ListenerMethod.receiveEvent(ListenerMethod.java:510)
at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:162)
at com.vaadin.ui.AbstractComponent.fireEvent(AbstractComponent.java:1166)
at com.vaadin.ui.AbstractField.fireValueChange(AbstractField.java:891)
at com.vaadin.ui.AbstractField.setValue(AbstractField.java:529)
at com.vaadin.ui.AbstractSelect.setValue(AbstractSelect.java:666)
at com.vaadin.ui.AbstractSelect.setValue(AbstractSelect.java:635)

When I do the setValue using opt.
Tks
Tullio

No further help?
Tks
Tullio

My suggestion is that the ‘id’ you’re trying to use as in the ‘setValue’ method has got to be the EXACT same object (memory-reference-wise) as the one that is already added in the combobox.

The way I usually do it is use a BeanItemContainer on which you can do ‘addBean([your_pojo]
)’ and then use the combo.setValue([your_pojo]
).

The tricky part is that the setValue has to be done using the object that has been added to the beanItemContainer.

the errormessage you get earlier is, imho, a small error in errormessaging within Vaadin (I could be mistaken though). The thing is, the return value for the ‘addItem’ method on a comboBox is of type ‘Bean’, though it it shown as the type of object you have added. Hence the confusion I guess.

Hope it helps :slight_smile:

use

select(itemId); to select a certain item in your ComboBox.

addValueChangeListener(new ValueChangeListener() {
            @Override
            public void valueChange(Property.ValueChangeEvent event) {
                event.getProperty().getValue());

            }
        });