views:

419

answers:

2

I have a IceFaces-form and several input fields.

Let's say I have this:

<ice:selectOneMenu id="accountMenu"
    value="#{accountController.account.aId}"
    validator="#{accountController.validateAccount}">
    <f:selectItems id="accountItems"
            value="#{accountController.accountItems}" />
</ice:selectOneMenu>

and this:

<ice:selectOneMenu id="costumerMenu"
    value="#{customerController.customer.cId}"
    validator="#{customerController.validateCustomer">
    <f:selectItems id="customerItems"
            value="#{customerController.customerItems}" />
</ice:selectOneMenu>

If I change one value, the respective validator is called, what is fine. But also the other validator is called, which is not fine, because the user get's an irritating message to insert a value to a field he maybe was just going to pay attention to. It's like poking the user with a stick to "Hurry up now!". BAD!

I thought the attribute "partialSubmit" is controlling this behaviour, so only the one DOM-part is submitted, which is affected by the user interaction, but if I declare the both components to be partially submitted, nothing changes. Still both validators are called if one component value is changed.

How can I prevent the whole form from being validated until it is submitted completely?

A: 

Try to perform ajax validation on onblur event (don't know how to do it with icefaces, but with richfaces it's simply an <a4j:support event="onblur" />)

Bozho
+2  A: 

When a partial submit is executed, the full JSF lifecycle is still executed. Thus, the validation phase is still processed, and all of the components in the component hierarchy are validated.

There are good reasons for this. A change in one component could cause a (potentially invalid) change in another component. For example, a selection from a selectOneMenu could set a value in a inputText.

ICEfaces alters processing in one significant way: During a partial submit, ICEfaces temporarily marks all components other than the one that triggered the sumbit as optional (required="false"). Thus, "required" validations are skipped. However, ICEfaces does not disable the other validations.

There are two possible solutions to this problem:

  1. Set immediate="true" in addition to partialSubmit. This changes the lifecycle slightly for the component when the partial submit is executed to perform the validation in the apply request values phase. This may cause the other validations to be skipped.

  2. Detect if a partial submit occurred in your custom validator. Skip the validation if it isn't the component that triggered the partial submit. Unfortunately, there isn't any documentation on how to detect a partial submit, but I found the solution in the source code for the com.icesoft.faces.application.PartialSubmitPhaseListener class.

    It turns out that ICEfaces adds two request parameters when a partial submit is executed:

    • ice.submit.partial - set to "true" to indicate that a partial submit was done.
    • ice.event.captured - contains the component ID of the component that generated the partial submit.

You can take advantage of these two parameters in your validation methods. Here's an example:

public void validateAccount(FacesContext context, 
  UIComponent component, Object value) 
{
  if(!partiallySubmitted(context) || 
     componentWasPartiallySubmitted(context, component)
    // Perform validation
  }

}

public boolean partiallySubmitted(FacesContext context) {
    ExternalContext externalContext = context.getExternalContext();
    Map parameterMap = externalContext.getRequestParameterMap();   

    return "true".equals(parameterMap.get("ice.submit.partial"));
}

public boolean componentWasPartiallySubmitted(FacesContext context, 
  UIComponent component) {
    ExternalContext externalContext = context.getExternalContext();
    Map parameterMap = externalContext.getRequestParameterMap();   

    String componentId = (String) parameterMap.get("ice.event.captured");

    return component.getId().equals(componentId);
}

Of course, accessing the two request parameters directly is probably unsupported. However, until the ICEfaces team provides a supported way to "detect" a partial submit, it may be your only option.

Jim Hurne
Out of curiosity, which of the two options worked for you? immediate=true, or detecting the partial submit in the validators?
Jim Hurne
None of the above, I did a redesign of my application at this point, but your answer helped me to gain more insight on the inner process of request handling.
bitschnau