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 , letconverter
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 , standarddatetimeconverter
(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 propertiesdate date
,string pattern
)this results in
23-09-2011
2011-09-23
09/23/2011use 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
Post a Comment