Como definir propriedades do conversor para cada linha de uma tabela de dados?

Eu criei um Converter personalizado de data e hora ISO:

 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 eu uso o Converter como na seguinte visão:

 

O problema é que, quando eu abro essa visão pela primeira vez, todas as propriedades são definidas na minha class Converter apenas uma vez e, em seguida, a tabela de dados processa e converte os valores com base nas propriedades iniciais.

Eu esperava que as propriedades fossem definidas por linha. Como posso conseguir isso?

Ao ponto, você esperava que as propriedades do conversor fossem definidas toda vez que uma linha de tabela fosse renderizada. Isso realmente não é verdade. O JSF criará apenas uma instância do conversor por componente quando a visualização for construída, ele não criará / reconfigurará o conversor toda vez que a linha for renderizada.

Existem várias maneiras de fazê-lo funcionar.

  • Passe os atributos dynamics como do componente e deixe o Converter interceptar nele. Você pode encontrar um exemplo aqui: JSF convertDateTime com fuso horário em tabela de dados . Isso pode ser usado como

         

  • Use uma function EL em vez de um Converter . Você pode encontrar um exemplo aqui: Facelets e JSTL (Convertendo uma Data em uma String para uso em um campo) . Isso pode ser usado como

      

  • Vincule o conversor e o DataModel da tabela de DataModel como uma propriedade do mesmo bean gerenciado. Dessa forma, você poderá definir as propriedades do conversor com base nos dados da linha antes de retorná-lo. Aqui está um exemplo básico de kickoff baseado nos componentes JSF padrão e no DateTimeConverter padrão (ele deve funcionar igualmente bem nos componentes PrimeFaces e com o seu conversor personalizado):

          

    com

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

    (a class Item é apenas um bean com duas propriedades Date date e String pattern )

    isto resulta em

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


  • Use OmniFaces lugar. Suporta a avaliação do tempo de renderização de EL nos atributos. Veja também o exemplo da mostra .

        
Intereting Posts