Question

I am trying to call a Wicket component's method from JavaScript and receive a value from this method which I want to use in the remaining bit of the JavaScript function which I used to call the component. However, I only seem to be able to call a Wicket component without waiting for it to produce a result.

More explicitly, I want to implement an AbstractDefaultAjaxBehavior which allows me to conditionally warn a user when he or she is leaving a page. This condition is for now determined by some OuterClass.shouldWarn method. However, even though this method gets called in my example below, I seem to be both unable to wait for a result of this method as well as I am unable to return some sort of result at all. Instead, the JavaScript just continues in its execution concurrently to the Java method call.

I hope the (not correctly running) example below clarifies my question:

 class PageExitWarningBehavior extends AbstractDefaultAjaxBehavior {

        @Override
        protected void respond(AjaxRequestTarget target) {
            target.appendJavaScript("return " + 
                (OuterClass.this.shouldWarn() ? "false" : "true"));
        }

        @Override
        public void renderHead(Component component, IHeaderResponse response) {

            String callbackFunktion = String.format(
                    "Wicket.Event.add(window, 'beforeunload', function( e ) {%n"
                          + "if( e ) { e.returnValue = '%s'; }%n"
                          + "var attrs = { 'u': '%s', 'c': '%s', 'ep': { } };%n"
                          + "Wicket.Ajax.get( attrs );%n"
                          + "return false;%n;"
                          + "});",
                    this.getCallbackUrl(),
                    OuterClass.this.getMarkupId());

            response.render(JavaScriptHeaderItem.forScript(callbackFunktion, 
                 "remind-of-running-task"));
        }

    }
Was it helpful?

Solution

I believe there is an easier way to intercept a page exit event than implementing your own AjaxBehavior:

Try implementing the following Behavior:

public class PageExitWarningBehavior extends Behavior {

  private boolean shouldWarn = false;

  @Override
  public void renderHead(Component component, IHeaderResponse response) {
    super.renderHead(component, response);
    if (shouldWarn) {
      response.render(new OnDomReadyHeaderItem("window.onbeforeunload = function (e) {"
    + "var message = 'Your confirmation message goes here.'," 
        + "e = e || window.event;" + "if (e) {"
    + "e.returnValue = message;" + "}" + "return message;" + "};"));
    }
  }

  @Override
  public void onEvent(Component component, IEvent<?> event) {
    super.onEvent(component, event);
    if (event.getPayload() instanceof PageExitWarningEvent) {
      PageExitWarningEvent exitEvent = (PageExitWarningEvent) event.getPayload();
    this.shouldWarn = exitEvent.isPageExitWarningEnabled();
    }
  }
}

In the renderHead method you conditionally add a simple javascript that triggers the browser to show a confirmation dialog when leaving the page (the javascript code is from this post).

In the onEvent method we listen if some other Wicket component has sent an PageExitWarningEvent to inform us that a warning should be displayed at all. You can send such an event from any Wicket component (such as a link or button) like this:

send(HomePage.this, Broadcast.BREADTH, new PageExitWarningEvent(true));

The PageExitWarningEvent class looks like this:

public class PageExitWarningEvent {

  private boolean pageExitWarningEnabled = false;

  public PageExitWarningEvent(boolean pageExitWarningEnabled) {
    this.setPageExitWarningEnabled(pageExitWarningEnabled);
  }

  public boolean isPageExitWarningEnabled() {
    return pageExitWarningEnabled;
  }

  public void setPageExitWarningEnabled(boolean pageExitWarningEnabled) {
    this.pageExitWarningEnabled = pageExitWarningEnabled;
  }

}

Let me know if that meets your requirements.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top