jsf - Using a "Please select" f:selectItem with null/empty value inside a p:selectOneMenu -
i'm populating <p:selectonemenu/>
database follows.
<p:selectonemenu id="cmbcountry" value="#{bean.country}" required="true" converter="#{countryconverter}"> <f:selectitem itemlabel="select" itemvalue="#{null}"/> <f:selectitems var="country" value="#{bean.countries}" itemlabel="#{country.countryname}" itemvalue="#{country}"/> <p:ajax update="anothermenu" listener=/> </p:selectonemenu> <p:message for="cmbcountry"/>
the default selected option, when page loaded is,
<f:selectitem itemlabel="select" itemvalue="#{null}"/>
the converter:
@managedbean @applicationscoped public final class countryconverter implements converter { @ejb private final service service = null; @override public object getasobject(facescontext context, uicomponent component, string value) { try { //returns item label of <f:selectitem> system.out.println("value = " + value); if (!stringutils.isnotblank(value)) { return null; } // makes no difference, if removed. long parsedvalue = long.parselong(value); if (parsedvalue <= 0) { throw new converterexception(new facesmessage(facesmessage.severity_error, "", "message")); } country entity = service.findcountrybyid(parsedvalue); if (entity == null) { throw new converterexception(new facesmessage(facesmessage.severity_warn, "", "message")); } return entity; } catch (numberformatexception e) { throw new converterexception(new facesmessage(facesmessage.severity_error, "", "message"), e); } } @override public string getasstring(facescontext context, uicomponent component, object value) { return value instanceof country ? ((country) value).getcountryid().tostring() : null; } }
when first item menu represented <f:selectitem>
selected , form submitted then, value
obtained in getasobject()
method select
label of <f:selectitem>
- first item in list intuitively not expected @ all.
when itemvalue
attribute of <f:selectitem>
set empty string then, throws java.lang.numberformatexception: input string: ""
in getasobject()
method though exception precisely caught , registered converterexception
.
this somehow seems work, when return
statement of getasstring()
changed from
return value instanceof country?((country)value).getcountryid().tostring():null;
to
return value instanceof country?((country)value).getcountryid().tostring():"";
null
replaced empty string returning empty string when object in question null
, in turn incurs problem demonstrated here.
how make such converters work properly?
also tried org.omnifaces.converter.selectitemsconverter
made no difference.
when select item value null
, jsf won't render <option value>
, <option>
. consequence, browsers submit option's label instead. specified in html specification (emphasis mine):
value = cdata [cs]
this attribute specifies initial value of control. if attribute not set, initial value set contents of option element.
you can confirm looking @ http traffic monitor. should see option label being submitted.
you need set select item value empty string instead. jsf render <option value="">
. if you're using converter, should returning empty string ""
converter when value null
. specified in converter#getasstring()
javadoc (emphasis mine):
getasstring
...
returns: zero-length string if value null, otherwise result of conversion
so if use <f:selectitem itemvalue="#{null}">
in combination such converter, <option value="">
rendered , browser submit empty string instead of option label.
as dealing empty string submitted value (or null
), should let converter delegate responsibility required="true"
attribute. so, when incoming value
null
or empty string, should return null
immediately. basically entity converter should implemented follows:
@override public string getasstring(facescontext context, uicomponent component, object value) { if (value == null) { return ""; // required spec. } if (!(value instanceof someentity)) { throw new converterexception("value not valid instance of someentity."); } long id = ((someentity) value).getid(); return (id != null) ? id.tostring() : ""; } @override public object getasobject(facescontext context, uicomponent component, string value) { if (value == null || value.isempty()) { return null; // let required="true" job on this. } if (!utils.isnumber(value)) { throw new converterexception("value not valid id of someentity."); } long id = long.valueof(value); return someservice.find(id); }
as particular problem this,
but returning empty string when object in question null, in turn incurs problem demonstrated here.
as answered on there, bug in mojarra , bypassed in <o:viewparam>
since omnifaces 1.8. if upgrade @ least omnifaces 1.8.3 , use <o:viewparam>
instead of <f:viewparam>
, shouldn't affected anymore bug.
the omnifaces selectitemsconverter
should work in circumstance. returns empty string null
.
Comments
Post a Comment