ListSelect with Objects?!

Hi,

I’m struggling with a listselect (Vaadin7!) in my application! Everything works with simple Strings, but now I want to use arbitrary objects.

I can’t find any clear example on the Internet/Vaadin site to tackle this!

I suspect I need items, properties and containers, but I don’t know how to start doing exactly that, sorry!

Any hint on how to setup a listselect with arbitrary objects, would be very much welcomed!

Thanks in advance!

Regards,
Gerard

Hi,

Our selects have a shamingly bad API for this most common use case. No proper typing nor built in support for lists, which makes it pretty hard to figure out without previous experience. Like you guessed, the custom Container-Item-Property API in Vaadin is what our selects use connect to your data to various select components. How you really should use it depends a bit in what format you get your options and how much of those options you have.

I’d suggest to take a look at my Maddon library. It has a TypedSelect component that simplifies the API quite a bit if you are doing a “singleselection”.
The test case for the component
also has examples of core Vaadin select usage with basic list of pojos. The add-on itself is available via
the Directory
.

cheers,
matti

Hi Matti,

Thanks for your suggestion, but I want to understand the container-item-property usage in relation to my nativeselect!

Let me illustrate my example to you:

I generate the list as follows:

[code]
MyObjectSet mos = new ObjectSet();

    nativeselFld.setItemCaptionPropertyId("name");
    nativeselFld.addContainerProperty("name", String.class, null);
    
    for (int i=0; i<mos.getObjects().size(); i++) {
        Item item = nativeselFld.addItem(es.getObjects().get(i));
        item.getItemProperty("name").setValue(es.getObjects().get(i).toString());
    }

[/code]The nativeselFld is a NativeSelect component defined elsewhere and the ObjectSet is the class holding the objects. The Object class overrides the toString method. The Object class is simple and defines an Object with just a name and a description. The name is returned using the toString method, because I want these names to appear in the nativeselFld.

The nativeselFld showes the items as aspected but I can’t get the nativeselFld.getValue and nativeselFld.setValue to work? I’m for example unable to set the nativeselFld to an Object from the set!?

Can you give any hint on how to tackle this?

Regards,
Gerard

Hi,

In your case, as you can use the toString from your pojo, I’d just suggest to use addItems method,
like in my example
. In this special case the usage is pretty simple with core Vaadin as well, only typing is missing but that is not that big deal once you figure it out. You can pass in either a Collection or an array and the toString form your instaces is used as a caption by default. I can’t know details about your ObjectSet implementation, but it looks like its getObjects() returns a java.util.List so just pass it to the field like this:

nativeselFld.setItems(mos.getObjects()); The getter and setter for value in the field then accepts an instance from your set. E.g. to make first object in your case to be selected by default should work like this:

nativeselFld.setValue(mos.getObjects().get(0));

Getting the selected value happens with a symmetric getter API.

I hope this helps. Just to be sure, you are not using the select in “multiselect” mode?

cheers,
matti

Hi,

Sorry, but the NativeSelect component doesn’t have a setItems method!

I use NativeSelect to ensure a single selection only!

The nativeselFld.setValue(mos.getObjects().get(0))! Those set/getValue methods only work in case work I add a String object with the addItem method NOT other objects! Why?

Regards,
Gerard

Hi,

Sorry, should always type code snippets with IDE, addItems was the method I ment, like in the linked example. It is a handy helper added in 7.2.

I’m pretty clueless what could go wrong without seeing the full code and implementations of your domain objects. What are the objects that you set as values? They must exist in the select as options before you the value. If it is not exactly the same instance, you naturally need to have properly implemented equals/hasCode methods implemented in your objects.

__
m

Hi Matti,

Okay, the Ethnicity class the actual objects of the NativeSelect looks like:

public class Ethnicity extends Item {

    private String comment;
    
    public Ethnicity() {
        comment = "";
    }
   
    public Ethnicity(String name, String description) {
        super(name,description);
        comment = "";
    }
    
    public void setComment(String value) {
        comment = value;
    }
    
    public String getComment() {
        return comment;
    }
    
    @Override
    public String toString() {
        return this.getName();
    

while the Item class contains:

[code]
public class Item {

private String name;
private String description;

public Item() {
    name = "";
    description = "";
}

public Item(String name, String description) {
    this.name = name;
    this.description = description;
}

public void setName(String value) {
    name = value;
}

public String getName() {
    return name;
}

public void setDescription(String value) {
    description = value;
}

public String getDescription() {
    return description;
}

@Override
public String toString() {
    return name;
}

public boolean equals(Item anotherItem) {
    if (this.name.equalsIgnoreCase(anotherItem.getName())) {
        return true;
    } else {
        return false;
    }
}

}
[/code]Something basic missing here!?

Regards,
Gerard

Hi,

To me it looks be scary taht you have overrideen the equals method, but haven’t written hashCode for it.
Always
, if you implement(override) equals method, you must also implement hashCode or your objects will cause a lots of headache when used in basic java collections - which are also used by Vaadin components. If you don’t care about performance at this point, just override hashCode to return 1 to see if this is the issue for you.

cheers,
matti

Hi,

I’m about getting desperate!

I added the following to the Item class:

    public int hashCode(Object o){
        return (int)this.name.hashCode() *
                    description.hashCode();
    }

and still no result! Also using return 1 in the hashCode method fails!

Regards,
Gerard

Hi, could you share your full example or a stripped down version in e.g. github? This is so basic use case that I’d bet I would in couple of minutes see whats wrong if I could see the full source code and debug the issue.

If you have business secrets you cannot publish, you could also use our
pro support
so our support engineers can look at this under NDA.

cheers,
matti

Hi Matti,

Finally, my colleague solved the issue!

He was looking at the hashcode method and was wondering about the
Object o
argument from my hashcode method, which I grabbed from the Internet!

Eclipse was also a bit complaining about it because the @Override annotation didn’t work, but neglected that!

But after we removed Object o from it like:

public int hashCode(){ return (int)this.name.hashCode() } the @Override annotation didn’t complain and it all worked!!!

But you of course gave the ultimate tip about the equal and hashcode methods, which is of course a basic issue, but didn’t realize that!

Thanks very much for your time and concern!

Regards,
Gerard

NP, I’m clad you solved this. Keeping developers happy with Vaadin is my job and that is mostly keeping people happy with Java :slight_smile:

cheers,
matti