21 Apr 2012

How to avoid validation of immediate inputs

Introduction
Setting the immediate attribute of JSF/ADF command components to true is not the silver bullet that can help you to avoid validation. This is explained in the Understanding the JSF Immediate attribute post. If you have immediate input controls on the same form, these controls are going to be validated in any case. But immediate input controls could be quite useful as it was shown in the Update model in the ValueChangeListener post.  So, let's say you have immediate required inputText and immediate commandButton (some "Cancel" button) on the same form. Leaving the inputText empty will cause a validation error when the commandButton is pressed.


This post is showing a technique of using some "super" Immediate button, that can help us to really avoid validation in any case. So, our "super" Immediate button looks like this:

   <af:commandButton text="Cancel" id="cb1" 
                      actionListener="#{TestBean.buttonActionListener}"        
                      immediate="true"
                      action="someAction">
                      
      <af:clientAttribute name="superImmediate" value="#{true}"/>                
      <af:clientListener method="catchActionEvent" type="action"/>
      <af:serverListener type="customButtonAction"
                         method="#{TestBean.customButtonActionListener}"/>

    </af:commandButton>                   


And a little bit of Java Script:
   <af:resource type="javascript">  
     
     // This hack avoids client-side validation for the "superImmediate"
     // commandComponents
     AdfActionEvent.prototype.isValidationNeeded = function()
       {
         return !this.getSource().getProperty("superImmediate");
       } 
       
    // Action event will cause server-side validation at the
    // Apply Request Values phase (for immediate button).
    // So we'll get validation error even if the client-side validation is suppressed
    // We need to catch the original Action event, cancel it and replace with our
    // custom event customButtonAction.
    function catchActionEvent(evt){
      AdfCustomEvent.queue(evt.getSource(), 'customButtonAction' , null, true); 
      evt.cancel();                  
    }   
    
   </af:resource>


And finally we need to emulate an Action Event in our customButtonActionListener in order to get the button's actionListener executed and the action processed:

  public void customButtonActionListener(ClientEvent clientEvent) {
      UIXCommand cb = (UIXCommand) clientEvent.getComponent();
      cb.broadcast(new ActionEvent(cb));
  }


That's it!

6 comments:

  1. Nice article. Solves a real world problem

    ReplyDelete
  2. Hi, I have a problem with this example, because I try to enable some buttons when I click the cancel button, but when that happen the buttons continue disabled, some Idea?

    I have the next code in the action of my button of cancel:

    public String accionBotonCancelarDetalle() {

    this.deshabilitarBotonesDetalle(false);
    this.setSeleccionRegistroDetalle("single");
    this.getDCIteratorBinding(this.getTablaConsultaDetalle()).executeQuery();
    return null;
    }

    ReplyDelete
  3. Hi Huan!
    I guess that the row enabling your buttons is this.deshabilitarBotonesDetalle(false);
    Am I right?
    What are you really doing in this method?

    ReplyDelete
  4. Thanks, it helped so much!!

    Rohit

    ReplyDelete

Post Comment