2011-09-23 10 views
10

He creado una costumbre de fecha y hora ISO Converter:¿Cómo establecer las propiedades del convertidor para cada fila de una tabla de datos?

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 restoreState(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 utilizar el Converter como <mh:IsoDateTimeConverter> en los próximos:

<p:dataTable value="#{imports.list}" var="item"> 
    <p:column> 
     <h:outputText value="#{item.balanceDate}" immediate="true"> 
      <mh:IsoDateTimeConverter type="#{webConst.ISO_DATE_CLASS}" pattern="#{webConst.ISO_DATE_FORMAT}"/> 
     </h:outputText> 
    </p:column> 
</p:dataTable> 

El problema es, cuando abra por primera vez este punto de vista, toda las propiedades se establecen en mi clase Converter solo una vez y luego la tabla de datos representa y convierte los valores en función de las propiedades iniciales.

Esperaba que las propiedades se configuraran por fila. ¿Cómo puedo conseguir esto?

Respuesta

24

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.

Existen varias formas de hacerlo funcionar.

  • pasan los atributos dinámicos como <f:attribute> del componente y dejar que la intercepción Converter en eso. Puede encontrar un ejemplo aquí: JSF convertDateTime with timezone in datatable. Esto puede ser usado como

    <h:outputText value="#{item.balanceDate}"> 
        <f:converter converterId="isoDateTimeConverter" /> 
        <f:attribute name="pattern" value="#{item.pattern}" /> 
    </h:outputText> 
    

  • uso de una función de EL en lugar de un Converter. Puede encontrar un ejemplo aquí: Facelets and JSTL (Converting a Date to a String for use in a field). Esto puede ser usado como

    <h:outputText value="#{mh:convertIsoDate(item.balanceDate, item.pattern)}" /> 
    

  • Enlazar el convertidor y la tabla de datos de DataModel como una propiedad del mismo bean gestionado. 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 patada de salida basado en componentes JSF estándar y estándar DateTimeConverter (que debería funcionar igual de bien en componentes PrimeFaces y con su convertidor de medida):

    <h:dataTable value="#{bean.model}" var="item"> 
        <h:column> 
         <h:outputText value="#{item.date}" converter="#{bean.converter}" /> 
        </h:column> 
    </h:dataTable> 
    

    con

    @ManagedBean 
    @ViewScoped 
    public class Bean implements Serializable { 
    
        private List<Item> items; 
        private DataModel<Item> 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<Item>(items); 
         converter = new DateTimeConverter(); 
        } 
    
        public DataModel<Item> getModel() { 
         return model; 
        } 
    
        public Converter getConverter() { 
         converter.setPattern(model.getRowData().getPattern()); 
         return converter; 
        } 
    
    } 
    

    (la clase Item es sólo un bean con dos propiedades Date date y String pattern)

    esto se traduce en

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


  • Uso OmniFaces<o:converter> lugar. Es compatible con la evaluación del tiempo de renderizado de EL en los atributos. Vea también the <o:converter> showcase example.

    <h:outputText value="#{item.balanceDate}"> 
        <o:converter converterId="isoDateTimeConverter" pattern="#{item.pattern}" /> 
    </h:outputText> 
    
Cuestiones relacionadas