s:selectItems: Customising the value

Posted by    |       Seam
<s:selectItems /> and <s:convertEntity /> output a key based on a numeric sequence to the page. How can I make it output something meaningful (e.g. the natural id of the entity)?

Why would you want to do this? Well, perhaps you want to use do some client side manipulation using JavaScript.

In Seam 2.0.1 I've added two mechanisms for doing this. You'll need to choose one based on your requirement.

By default <s:selectItems value="#{people}"/> uses, as its itemValue (which is rendered as the value attribute on <option />) each item in the list. Perhaps you want to use some associated object (for example, #{person.employeeNumber}). In this case it's as easy as:

<h:selectOneMenu value="#{project.teamLeadEmployeeNumber}">
  <s:selectItems value="#{people}" var="person" label="#{person.name}" itemValue="#{person.employeeNumber}" />
</h:selectOneMenu>

Great! But what if you want to use <s:convertEntity /> (which doesn't play nicely with this approach)? Why? Well the value referenced by the itemValue attribute is passed to <s:convertEntity />.

So, there is a second, slightly more complex option, if you want to use <s:convertEntity /> with custom keys - you need to provide a strategy for converting the entity Identifier to the output value and back.

First, override the org.jboss.seam.ui.entityIdentifierStore component:

@Name("org.jboss.seam.ui.entityIdentifierStore")
@Scope(PAGE)
public class MyEntityIdentifierStore extends EntityIdentifierStore {

Then, override the public String put(Identifier identifier, Object entity) method:

  public String put(Identifier identifier, Object entity) {
    if (entity instanceof Person) {
      Person person = (Person) entity;
      return "person:" + person.getEmployeeNumber();
    } else {
      return super.put(identifier, entity);
    }
  }

Finally, override public Identifier get(String key):

  public Identifier get(String key) {
    if (key.startsWith("person")) {
      String id = key.substring(6, key.length());
      return new EntityIdentifier(Person.class, new Long(id));
    } else {
      return super.get(key);
    }
  }
}

I've used EntityIdentifier as I'm using JPA, but of course of you could use HibernateEntityIdentifier if you are using plain Hibernate.

I hope you've learnt in this tutorial how to customise <s:selectItems />, BUT I also hope it highlights what I think is one of the most powerful features of Seam - that you can easily override the core components of Seam!


Back to top