Tuesday, July 24, 2012

JSF datatable and primitive type

suppose you have a list of integer, you want edit/delete them. h:dataTable seems to be a natural fit.
<h:datatable value="#{mylist}" var="{intitem}">
 <h:inputtext value="#{intitem}"/><h:inputtext>
</h:datatable>

Quickly you will find any value you set in the web interface will be ignored by the datatable. ui:repeat in facelet gives the same result.

It turns out that the var in datatable has to be an object type. Inside of the datatable, you access/modify the var's property. You can not modify the var itself. 

Modifying a var is like
var=newvalue;
in java
Here the var is a temporay reference.  The temporary reference points to original value in the list before modification. After the form is submitted, you basically create a new object, and make the temporary reference point to the newly created object.   The original value is not touched. The original list still has its values untouched.

This rule applies to string too.
To solve this, you need a wrapper type like this.

public class ValueHolder<T extends Serializable> implements Serializable
    {        private static final long serialVersionUID = 1L;
        public T value;
        public ValueHolder()
        {
        }
        public ValueHolder(T v)
        {
            value=v;
        }
        public T getValue()
        {
            return value;
        }
        public void setValue(T v)
        {
            value=v;
        }
        
    }
The primitive list has to be changed to a list of ValueHolder.  By this way, you change object access into property access.

<h:datatable value="#{mywrapperlist}" var="{intitem}">
 <h:inputtext value="#{intitem.value}"/><h:inputtext>
</h:datatable> 

No comments:

Post a Comment