¿Cómo establecer las propiedades del convertidor para cada fila de una tabla de datos?

He creado un Converter fecha y hora ISO personalizado:

 public class IsoDateTimeConverter implements Converter, StateHolder { private Class type; private String pattern; private boolean transientValue = false; public void setType(Class type) { this.type = type; } public void setPattern(String pattern) { this.pattern = pattern; } @Override public Object getAsObject(FacesContext context, UIComponent component, String value) throws ConverterException { if (StringCheck.isNullOrEmpty(value)) { throw new ConverterException("value not specified"); } try { if (IsoDate.class.equals(type)) { if (WebConst.ISO_DATE_NONE.equals(value)) { return IsoDate.DUMMY; } else { //TODO User spezifische TimeZone auslesen return new IsoDate(value, TimeZone.getDefault().getID()); } } else if (IsoTime.class.equals(type)) { if (WebConst.ISO_TIME_NONE.equals(value)) { return IsoTime.DUMMY; } else { //TODO User spezifische TimeZone auslesen return new IsoTime(value, TimeZone.getDefault().getID()); } } else if (IsoTimestamp.class.equals(type)) { if (WebConst.ISO_TIMESTAMP_NONE.equals(value)) { return IsoTimestamp.DUMMY; } else { //TODO User spezifische TimeZone auslesen return new IsoTimestamp(value, TimeZone.getDefault().getID()); } } else { throw new ConverterException("value not convertible"); } } catch (Exception e) { throw new ConverterException(e.getMessage()); } } @Override public String getAsString(FacesContext context, UIComponent component, Object value) throws ConverterException { if (value == null) { throw new ConverterException("value not specified"); } if (IsoDate.class.equals(value)) { IsoDate isoDate = (IsoDate) value; if (isoDate.isDummy()) { return WebConst.ISO_DATE_NONE; } else { //TODO User spezifische TimeZone auslesen return isoDate.toString(pattern, TimeZone.getDefault().getID(), false); } } else if (IsoTime.class.equals(value)) { IsoTime isoTime = (IsoTime) value; if (isoTime.isDummy()) { return WebConst.ISO_TIME_NONE; } else { //TODO User spezifische TimeZone auslesen return isoTime.toString(pattern, TimeZone.getDefault().getID(), false); } } else if (IsoTimestamp.class.equals(value)) { IsoTimestamp isoTimestamp = (IsoTimestamp) value; if (isoTimestamp.isDummy()) { return WebConst.ISO_TIMESTAMP_NONE; } else { //TODO User spezifische TimeZone auslesen return isoTimestamp.toString(pattern, TimeZone.getDefault().getID(), false); } } else { throw new ConverterException("value not convertible"); } } @Override public Object saveState(FacesContext context) { return new Object[]{type, pattern}; } @Override public void restreState(FacesContext context, Object state) { type = (Class) ((Object[]) state)[0]; pattern = (String) ((Object[]) state)[1]; } @Override public boolean isTransient() { return transientValue; } @Override public void setTransient(boolean transientValue) { this.transientValue = transientValue; } } 

Y utilizo el Converter como en la siguiente vista:

 

El problema es que cuando abro esta vista por primera vez, todas las propiedades se configuran en mi clase de Converter solo una vez y luego la tabla de datos representa y convierte los valores en función de las propiedades iniciales.

Esperé que las propiedades se establezcan por fila. ¿Cómo puedo conseguir esto?

Hasta el punto, esperaba que las propiedades del convertidor se establezcan cada vez que se representa una fila de tabla de datos. Esto de hecho no es verdad. JSF creará solo una instancia de convertidor por componente cuando se construirá la vista, no creará / reiniciará el convertidor cada vez que se represente la fila.

Hay varias formas de hacerlo funcionar.

  • Pase los atributos dynamics como del componente y deje que el Converter intercepte. Aquí puede encontrar un ejemplo: JSF convertDateTime con zona horaria en datatable . Esto puede ser usado como

         

  • Use una función EL en lugar de un Converter . Puede encontrar un ejemplo aquí: Facelets y JSTL (Convertir una fecha en una cadena para usar en un campo) . Esto puede ser usado como

      

  • Vincular el DataModel del convertidor y de la tabla de DataModel como una propiedad del mismo bean administrado. De esta forma, podrá establecer las propiedades del convertidor en función de los datos de la fila antes de devolverlo. Aquí hay un ejemplo básico de inicio basado en componentes JSF estándar y DateTimeConverter estándar (debería funcionar igual de bien en los componentes de PrimeFaces y con su convertidor personalizado):

          

    con

     @ManagedBean @ViewScoped public class Bean implements Serializable { private List items; private DataModel model; private DateTimeConverter converter; @PostConstruct public void init() { items = Arrays.asList( new Item(new Date(), "dd-MM-yyyy"), new Item(new Date(), "yyyy-MM-dd"), new Item(new Date(), "MM/dd/yyyy")); model = new ListDataModel(items); converter = new DateTimeConverter(); } public DataModel getModel() { return model; } public Converter getConverter() { converter.setPattern(model.getRowData().getPattern()); return converter; } } 

    (la clase de Item es solo un frijol con dos propiedades Date date y String pattern )

    esto resulta en

    23-09-2011
    2011-09-23
    23/09/2011


  • Use OmniFaces lugar. Es compatible con la evaluación del tiempo de renderizado de EL en los atributos. Ver también el ejemplo showcase .