Knight of the round table

wansong

Selecting from a list of entities

<rich:pickList value="#{manageCountryGroup.selectedCountries}" sourceListWidth="200" targetListWidth="200">
              <s:selectItems value="#{availableCountriesQuery.resultList}" var="c" label="#{c.name}" itemValue="#{c}" >       
                </s:selectItems>
                <s:convertEntity/>
              <a4j:support action="#" event="onlistchanged" reRender="cgManagementPanel" ajaxSingle="true" />
            </rich:pickList>


Selecting from a list of entities

See http://docs.jboss.org/seam/latest/reference/en/html/controls.html

  • Use <s:selectItems> to produce a list of labeled select items from a list of entities.
  • Use <s:convertEntity> to map back and forth between the select items and the actual entity values. This is what allows you to map the value of the <h:selectOneMenu> directly to the property of the referencing entity (e.g. a property that is a many-to-one).
<h:selectOneMenu value="#{person.continent}" required="true">                        (1)

<s:selectItems value="#{continents.resultList}" var="continent" (2)

label="#{continent.name}" noSelectionLabel="Please Select..."/>

<s:convertEntity /> (3)

</h:selectOneMenu>

  1. person is an entity that has been outjected into the conversation. It has a 'continent' property which is many-to-one association with another entity.
  2. continents is a Seam application framework 'query' object. This 'query' object should probably use a Seam-managed EntityManager because we want have the Hibernate session-in-view behavior so we don't get lazy initialization exceptions when rendering the labels, etc.
  3. s:convertEntity will convert the Continent entities into values for the HTML select, and vice versa.

Tips

  1. To avoid LazyInitializationExceptions and/or writing extra code in your EJB/Controller bean to initialize objects, use session in view.
  2. For required fields, put required="true" on the selectOneMenu and override javax.faces.component.UIInput.REQUIRED in messages.properties (see Standard Faces Error Messages).

Select from an enum

This works just like selecting an entity, but <s:convertEnum/> is used instead.


XHTML:

<h:selectOneMenu id="marketStatus" value="#{person.status}"         (1)

required="true">

<s:selectItems value="#{enumLists.statusArray}" var="status" (2)

label="#{status}"

noSelectionLabel="Select a status..."/>

<s:convertEnum/>

</h:selectOneMenu>

EnumLists.java:

@Name("enumLists")

@Scope(ScopeType.STATELESS)

public class EnumLists

{

public Status[] getStatusArray()

{

return Status.values();

}

}

  1. person is an entity that has been outjected into the conversation. It has a 'status' property which is an enum.
  2. We need to expose the values of the enum as a list or an array, so we make a stateless POJO component with getters that returns arrays for various enums called enumLists.

Multi-select from an enum

Here we use a selectManyCheckbox.


<h:selectManyCheckbox id="roles" 

layout="pageDirection" value="#{person.roles}"

required="true">

<s:selectItems value="#{enumLists.roleArray}" var="role"

label="#{role}"/>

<s:convertEnum/>

</h:selectManyCheckbox>

Unfortunately, Seam's convertEnum can't handle multi selects yet. This example will yeild a strange exception:

java.lang.IllegalArgumentException: java.util.List is not an enum type

Luckily, it's very easy to create custom converter tags with Facelets. Here is the converter class that handles both ordinary enums and multi-selects:

package eg;



import javax.faces.component.*;

import javax.faces.context.*;

import javax.faces.convert.*;

import javax.faces.el.ValueBinding;

import java.util.List;

import java.util.Collection;



/**

* Converter for enum multi-selects.

* <br>User: Joshua Davis

* Date: May 16, 2007

* Time: 7:25:58 AM

*/

public class EnumListConverter implements Converter

{

@SuppressWarnings({"unchecked"})

public Object getAsObject(FacesContext context,

UIComponent comp,

String value)

throws ConverterException

{

ValueBinding binding = comp.getValueBinding("value");

Class enumType = binding.getType(context);

if (enumType.isEnum()) // Single enum?

return Enum.valueOf(enumType, value);

else // List of enums.

{

// Find the s:selectItems so we can get the enum.

List children = comp.getChildren();

for (Object child : children)

{

if (child instanceof UIComponent)

{

UIComponent c = (UIComponent) child;

ValueBinding b = c.getValueBinding("value");

Class t = b.getType(context);

// Array of enums: use the component type.

if (t.isArray() && t.getComponentType().isEnum())

{

t = t.getComponentType();

return Enum.valueOf(t,value);

}

else

{

Object v = b.getValue(context);

// Collection of enum values, get the type of the first element.

if (v instanceof Collection)

{

t = ((Collection) v).iterator().next().getClass();

return Enum.valueOf(t,value);

}

}

}

}

throw new ConverterException("Unable to find selectItems with enum values!");

}

}



public String getAsString(FacesContext context,

UIComponent component,

Object object)

throws ConverterException

{

if (object == null) {

return null;

}



return ((Enum) object).name();

}



}

Retrieved from "http://shrubbery.mynetgear.net/wiki/Select_lists_with_Seam"


posted on 2009-04-14 11:01 w@ns0ng 阅读(980) 评论(0)  编辑  收藏 所属分类: Jboss Seam


只有注册用户登录后才能发表评论。


网站导航: