Friday, March 26, 2010

Immediate, Autosubmit, and Validation

Often users understand how to use immediate on buttons and form controls to avoid validation, however they sometimes have problems using immediate and autoSubmit. So what's different about using autoSubmit and immediate?

Let's start at the beginning, components that implement the interfaces below support an attribute called "immediate". In both cases processing is moved up to the APPLY REQUEST VALUES phase.

  • ActionSource: (an example is commandButton.) An ActionEvent is normally delivered in INVOKE APPLICATION. When immediate is true the action event delivery is moved up to the APPLY REQUEST VALUES phase. An ActionEvent always results in renderResponse() being called implicitly in the default ActionListener (Application.getActionListener()), whether or not an "action" is attached.
  • EditableValueHolder: the validation and valueChangeEvent usually take place in the PROCESS VALIDATIONS phase. When immediate is true the component's value will be converted and validated in the APPLY REQUEST VALUES phase, and ValueChangeEvents will be delivered in that phase as well.


So in JSF there's a default actionListener which calls renderResponse. That means that when a button is immediate renderResponse will be called during apply request values, and the validation phase will be skipped.

Let's look at the following example, note that when you press submit you don't get a required field error:



<af:selectBooleanRadio valueChangeListener="#{validate.toggle}" id="show3"
text="Show" group="group3"
value="#{validate.show3}" immediate="true"/>
<af:selectBooleanRadio id="hide3" text="Hide" group="group3"
value="#{validate.hide3}" immediate="true"/>
<af:panelGroupLayout partialTriggers="cb2" id="pgl8">
<af:inputText label="Required Field" required="true"
rendered="#{validate.show3}" id="it3"/>
</af:panelGroupLayout>
<af:commandButton text="submit" id="cb2" immediate="true"/>


and in the validate bean here's the toggle method

  
public void toggle(ValueChangeEvent vce)
{
setShow3(Boolean.TRUE.equals(vce.getNewValue()));
}



Adf Faces adds the concept of "autoSubmit" to form controls, when "autoSubmit" is true the component will automatically submit when the value is changed. When people combine autoSubmit and immediate on a form control, they often expect to skip the validation phase like they would if they had used an immediate button, but there is no default listener for valueChangeEvents.

You might think you can just change the jspx to this without changing the toggle method.


<af:selectBooleanRadio autoSubmit="true"
valueChangeListener="#{validate.toggle}" id="show3"
text="Show" group="group3" value="#{validate.show3}"
immediate="true"/>
<af:selectBooleanRadio autoSubmit="true" id="hide3" text="Hide" group="group3"
value="#{validate.hide3}" immediate="true"/>
<af:panelGroupLayout partialTriggers="show3 hide3" id="pgl8">
<af:inputText label="Required Field" required="true"
rendered="#{validate.show3}" id="it3"/>
</af:panelGroupLayout>


However you also have to change the toggle method to call FacesContext.renderResponse, like so:

  
public void toggle(ValueChangeEvent vce)
{
setShow3(Boolean.TRUE.equals(vce.getNewValue()));
FacesContext.getCurrentInstance().renderResponse();
}

3 comments:

  1. Hi,
    Is there a way to invoke ValueChangeEvent with AutoSubmit = false?

    If not, how can I "keep" my selected value on the screen?

    ReplyDelete
  2. Thank-you so much! I've been wrestling with this problem all day!!!

    ReplyDelete
  3. Hmmm, yup no doubt Google is finest in support of blogging however today word press is also fastidious as a blogging since its Web optimization is nice defined already.

    -----------------
    Immersion heater replacement

    ReplyDelete