Monday, January 31, 2011

Preventing multiple form submits in ICEFaces by disabling commandButton

I created a form in ICEFaces 2 to upload a file. ICEFaces 2 has a new component for files, called the fileEntry (see http://wiki.icefaces.org/display/ICE/FileEntry). The old inputFile component has been removed from ICEFaces 2. Uploading a file takes a while, and I quickly noticed the user could click the "upload" button multiple times while the upload was in progress. This is obviously something you want to prevent. There is a very easy approach to this: just disable the submit button once it has been pressed. All you need to do is add this code to the commandButton tag:
onclick="this.disabled=true"
This works fine, and if you always go to a new page after the form has been submitted this is all you have to do. In most applications this unfortunately won't be the case: if something goes wrong with the file upload or if some other form components fail validation, you will want to stay on the same page, giving the user a warning message and allowing him to try again. The problem is that your commandButton is now disabled, so the user can't try again...
Re-enabling the commandButton when the action finishes is not as easy as it may seem: there's no "onAfterSubmit" action or something similar on the form. My first try was to add the disabled property with a value of "false":
disabled="false"
I thought that ICEFaces would re-evaluate the form after the submit, causing it to reset the disabled property to false. Unfortunately ICEFaces is smarter than that, and uses a technique called "partial dom updates". What this means is it checks if any of the components properties were changed in the action and it will only update those components whose properties have actually changed. This is a smart technique, since it reduces http traffic. It also means that our commandButton will not be updated, since for ICEFaces nothing changed to this component (it isn't aware of the JavaScript function we performed on it). This means we will have to trick ICEFaces into thinking a property of our commandButton has actually changed, causing it to refresh the commandButton. I choose to "abuse" the styleClass property for this use. I set it to:
styleClass="#{backingBean.randomValue}"
Then in my backing bean I implemented the getter for this value as follows:
public String getRandomValue() {
return "a" + System.currentTimeMillis();
}
This ensures we will get a different value for the styleClass property on each form submit. This will trick ICEFaces into thinking the commandButton has changed, causing it to refresh it and setting the disabled value to false, effectively re-enabling our commandButton.

I agree this approach isn't very clean, but it's the only technique I found to accomplish this in ICEFaces. If anyone knows of a better way, I'd be glad to know!

9 comments:

  1. A really smart way to handle the double click issue. Thanks!

    ReplyDelete
  2. Could you provide the steps for fileentry tag to use

    santhosh

    ReplyDelete
  3. Hi Santosh,

    The documentation for the fileentry component can be found here: http://wiki.icefaces.org/display/ICE/FileEntry. Basically you add the tag to your facelet and then you add a listener to your backing bean that will be called when a file is uploaded. Please note that this is for ICEFaces 2.x. For ICEFaces 1.x please see http://component-showcase.icefaces.org/component-showcase/showcase.iface and selet "file upload".

    ReplyDelete
  4. Hi

    Thanks for your reply

    I am using icefaces 2 and i have tried the same which you have mentioned and getting session expired exception

    ReplyDelete
  5. When are you getting the session expired? After you have uploaded a file? Could it be that you are uploading a very big file which takes a lot of time? If so, you should probably increase the session-timeout in the web.xml file, like this:
    <session-config>
    <session-timeout>120</session-timeout>
    </session-config>
    This sets the timeout to 120 minutes.

    ReplyDelete
  6. Mathiasdegroof

    Thanks for your quick response and i could resolve. File uploading is successfull. The session problem was not due to file.
    I did mistake in calling backing bean

    Santhosh

    ReplyDelete
  7. Thank you so much Mathias.I used your logic and its working fine.I researched for this logic almost 3 days. At last i found u r logic.you r too smart.keep it up

    Regards,
    Kiran

    ReplyDelete
  8. I was just looking for this shit !! Thanks ...

    ReplyDelete
  9. This ensures we will get a different value for the styleClass property on each form submit. This will trick ICEFaces into thinking the commandButton has changed, causing it to refresh it and setting the disabled value to false, effectively re-enabling our commandButton. pandora necklace usa , pandora necklace wholesale france ,

    ReplyDelete