Come impostare le proprietà del convertitore per ogni riga di un datatable?

Ho creato un Converter data e ora ISO personalizzato:

 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; } } 

E io uso il Converter come nella seguente vista:

 

Il problema è che quando apro per la prima volta questa vista, tutte le proprietà sono impostate nella class Converter solo una volta e quindi il datatable esegue il rendering e converte i valori in base alle proprietà iniziali.

Mi aspettavo che le proprietà fossero impostate su una base per riga. Come posso raggiungere questo objective?

Al punto, ci si aspettava che le proprietà del convertitore venissero impostate ogni volta che una riga datatable è rappresentata. Questo non è davvero vero. JSF creerà solo una istanza di convertitore per componente quando la vista deve essere costruita, non creerà / ripristinerà il convertitore ogni volta che la riga viene sottoposta a rendering.

Ci sono diversi modi per farlo funzionare.

  • Passa gli attributi dinamici come del componente e lascia intercettare il Converter . Puoi trovare un esempio qui: JSF convertDateTime con fuso orario in datatable . Questo può quindi essere usato come

         

  • Usa una funzione EL invece di un Converter . Puoi trovare un esempio qui: Facelets e JSTL (Conversione di una data in una stringa da utilizzare in un campo) . Questo può quindi essere usato come

      

  • Associare il convertitore e DataModel di DataModel come proprietà dello stesso bean gestito. In questo modo sarai in grado di impostare le proprietà del convertitore in base ai dati della riga prima di restituirlo. Ecco un esempio di kickoff di base basato su componenti JSF standard e DateTimeConverter standard (dovrebbe funzionare allo stesso modo su componenti PrimeFaces e con il tuo convertitore personalizzato):

          

    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 class Item è solo un bean con due proprietà Date date e String pattern )

    questo risulta in

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


  • Utilizzare invece OmniFaces . Supporta la valutazione del tempo di rendering di EL negli attributi. Vedi anche l’esempio di vetrina .