Wicket in Action

Preventing double Ajax requests in 3 lines of code

05 December 2008, by dashorst

One question is recurring on our user list: how can I prevent a user from clicking an Ajax link multiple times? There are several solutions to this problem, but today I thought up possibly the simplest solution yet for Wicket applications using the infrastructure that is already in place for displaying custom Ajax indicators.

Wicket provides the IAjaxIndicatorAware interface where you can identify a piece of markup that is displayed when Wicket is processing an Ajax request, and hidden when the request was completed. Letting your page implement this interface and including a coverall div in your markup is enough to stop your users from sending multiple requests quickly after one another. Take a look at the following Wicket page:

 1 package com.mycompany;
 3 import org.apache.wicket.markup.html.WebPage;
 4 import org.apache.wicket.ajax.*;
 5 import org.apache.wicket.ajax.markup.html.*;
 7 public class HomePage extends WebPage 
 8                       implements IAjaxIndicatorAware {
 9     public HomePage() {
10         add(new AjaxLink("link") {
11             public void onClick(AjaxRequestTarget t) {
12                 try { Thread.sleep(5000); } catch(Exception e) {}
13             }
14         });
15     }
16     public String getAjaxIndicatorMarkupId() {
17         return "veil";
18     }
19 }

Line 8 lets our page implement the necessary interface, and lines 16-18 implement the required method provided by this interface. In this method we return the markup identifier (DOM id) for our coverall, in this case called veil. The AjaxLink just sleeps for 5 seconds in the event handler, but you can do your dirty work there. This is just an example of course.

In our markup we now need to create the coverall so that Wicket is able to show and hide this veil. The markup in the next example shows the complete page markup:

        <title>Wicket Quickstart Archetype Homepage</title>
        <a href="#" wicket:id="link">Show veil</a>
        <div id="veil" style="display:none;position:absolute;top:0;left:0;z-index=99999;background-color:black;width:100%;height:100%;color:white">
            <h1>Can't touch this</h1>

And that is all there's to it. Done. Finito. Ready. Complete. Can this be improved? Yes:

  • Normal requests aren't covered (see a possible solution)
  • IE6 is a bitch
  • Styling could be better

And probably more, but for normal browsers and just Ajax requests, this is the easiest way to hack this in.