Reputation: 37061
I have the following page/bean structure (using myfaces 2.0.11 + tomcat 6)
I have one checkbox that when checked the h:inputtext
(which is connected to an Integer
variable in my bean) next to him is enabled and when the checkbox is unchecked the input is disabled, and I have a submit button that submits them both (entire form)
here is the code
<h:form prependId="false">
<h:selectBooleanCheckbox id="my_len" value="#{myBean.myLenBool}">
<f:ajax render="my_len_input_wrapper"/>
</h:selectBooleanCheckbox>
<h:panelGroup id="my_len_input_wrapper">
<h:inputText value="#{myBean.myLen}" id="my_len_input"
disabled="#{not myBean.myLenBool}" required="#{myBean.myLenBool}">
<f:validateLongRange minimum="1"/>
</h:inputText>
<h:message for="my_len_input"/>
</h:panelGroup>
<h:commandButton action="#{myBean.submit}" value="submit">
<f:ajax render="@form" execute="@form"></f:ajax>
</h:commandButton>
</h:form>
Bean code
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
@ManagedBean
@SessionScoped
public class myBean {
Integer myLen;
boolean myLenBool;
public Integer getMyLen() {
return myLen;
}
public void setMyLen(Integer myLen) {
this.myLen = myLen;
}
public boolean isMyLenBool() {
return myLenBool;
}
public void setMyLenBool(boolean myLenBool) {
this.myLenBool = myLenBool;
}
public void submit() {
// submit
}
}
The scenario is as following
1) check the checkbox (the input will be enabled)
2) enter an invalid value (for example 0.5) , its invalid cause myLen
is a Integer
3) hit submit -> a error message will be shown in h:message
cause of conversion error
4) uncheck the checkbox (it will disable the inputtext)
5) hit submit <--- form is not being submitted cause of the conversion error?!?!
So the question is: how can I submit the form with disabled input that got conversion error???
The only solution I found so far is writing my own custom converter
that ignores conversion if the field is disabled
@FacesConverter("APCustomConverter")
public class APCustomConverter extends IntegerConverter{
@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
if (component.getAttributes().get("disabled") != null && component.getAttributes().get("disabled").equals(true)) {
return null;
}
Object retValue = super.getAsObject(context, component, value);
return retValue;
}
}
Was hoping for a better solution than mine (using CustomConverter
),
A bit off/not so off topic:
This conversion error eventually had lead me to a really annoying scenario in which: when I used discard button with only render="@form" the state of the checkbox and the input went so wrong that after clicking discard -> the checkbox remained checked (although it shouldn't cause form wasn't really submitted) and the input was disabled and not readonly cause the real checkbox value was false, AND when i hit submit again the checkbox became really checked but the input got himself a null value (all this cause null pointers exception on server), so eventually I had to use <f:actionListener type="org.omnifaces.eventlistener.ResetInputAjaxActionListener" />
by omnifaces in the discard button.
Upvotes: 2
Views: 1660
Reputation: 31659
Tested with Mojarra 2.1.26 and MyFaces 2.0.11. When unchecking the checkbox, Mojarra updates the h:inputText
and leaves it blank, which is the expected behaviour because the value has never reached the model (validation error). However, MyFaces only updates it to disable mode, leaving the old input value there.
That seems like a MyFaces issue, not solved even in the latest (2.1.12-2.0.18) branch versions. In fact, if you want to skip some element's conversion/validation depending on its state, writing a custom converter/validator is the way to go, but in your case the issue is tied to MyFaces' ajax cycle, which should work as Mojarra's one does.
As a solution you have three possible choices:
Upvotes: 3