jsf - How to set converter properties for each row of a datatable? -


i have created custom iso date time converter:

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

and use converter <mh:isodatetimeconverter> in following view:

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

the problem is, when first open view, properties set in converter class once , datatable renders , converts values based on initial properties.

i expected properties set on per-row basis. how can achieve this?

to point, expected converter's properties set every time datatable row rendered. indeed not true. jsf create 1 converter instance per component when view built, not create/reset converter each time row rendered.

there several ways work.

  • pass dynamic attributes <f:attribute> of component , let converter intercept on that. can find example here: jsf convertdatetime timezone in datatable. can used as

    <h:outputtext value="#{item.balancedate}">     <f:converter converterid="isodatetimeconverter" />     <f:attribute name="pattern" value="#{item.pattern}" /> </h:outputtext> 

  • use el function instead of converter. can find example here: facelets , jstl (converting date string use in field). can used as

    <h:outputtext value="#{mh:convertisodate(item.balancedate, item.pattern)}" /> 

  • bind converter , datatable's datamodel property of same managed bean. way able set converter's properties based on row data before returning it. here's basic kickoff example based on standard jsf components , standard datetimeconverter (it should work equally on primefaces components , custom converter):

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

    with

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

    (the item class bean 2 properties date date , string pattern)

    this results in

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


  • use omnifaces <o:converter> instead. supports render time evaluation of el in attributes. see the <o:converter> showcase example.

    <h:outputtext value="#{item.balancedate}">     <o:converter converterid="isodatetimeconverter" pattern="#{item.pattern}" /> </h:outputtext> 

Comments

Popular posts from this blog

php - Invalid Cofiguration - yii\base\InvalidConfigException - Yii2 -

How to show in django cms breadcrumbs full path? -

ruby on rails - npm error: tunneling socket could not be established, cause=connect ETIMEDOUT -