drecute
drecute

Reputation: 758

Calling a Javascript function from Wicket

I want to pass the output of a block of javascript code in html to its corresponding wicket component. I tried AbstractDefaultAjaxBehaviour and it doesn't seem to work.

Here's what I'm working with:

HTML

// In <body>
<div wicket:id="container">
<script type="text/javascript" wicket:id="channelScript">

  function initChannel() {
    window.alert('got it');
  }

</script>
</div>

private WebMarkupContainer container = new WebMarkupContainer("container");
private Label channelScript = new Label("channelScript", "initChannel();");

add(container);
final AbstractDefaultAjaxBehavior channel = new AbstractDefaultAjaxBehavior() {
    protected void respond(final AjaxRequestTarget target) {
    channelScript.setEscapeModelStrings(false);
        target.add(channelScript); // initChannel is not triggerred
    }
};
container.add(channel);

I also tried this:

add(new AjaxEventBehavior("onload") {
  @Override
  protected void onEvent(AjaxRequestTarget target) {
    channelScript.setEscapeModelStrings(false);
    target.add(new Label(channelScript));
  }
}

Please what am I doing wrong? Thanks

UPDATE

I will be passing series of variables from wicket to JS such that every javascript output is displayed using wicket component. I just realized that I will have to make do with dom ready state to begin the interaction. So that's fine. But then I'm still confused and clueless about how the wicket component will change state to receive updated response from javascript. Is there a wicket component that triggers itself asynchronously?

Upvotes: 3

Views: 22714

Answers (3)

thrau
thrau

Reputation: 3100

I've been working on a Wicket 6 extension called wicket-js which allows you to do this in a very convenient and clean way.

Code for your use case could look something like this

add(new JsBehavior() {
    @Override
    protected IJavaScript domReadyJs() {
        return new JsCall("initChannel");
    }
});

which translates into what @Till has already provided as a native Wicket solution.


If you want the alert in there you could do this

add(new JsBehavior() {
    @Override
    protected IJavaScript domReadyJs() {
        return new JsStatements(
            new JsCall("alert", "got it"),
            new JsCall("initChannel")
        );
    }
});

Upvotes: 1

Till
Till

Reputation: 994

Don't use a Label as script container. Wicket has some proper ways to do that. The following code would be on option (assuming that you are on wicket 1.5)

    @Override
public void renderHead(final Component component, final IHeaderResponse response)
{
    super.renderHead(component, response);

    response.renderJavaScript("initChannel();", "myScriptID");
}

If you want to perform a script after you site was fully loaded, you can use this:

response.renderOnLoadJavaScript("doSomething();");

In wicket 1.4 this works differently. You have to use HeaderContributors there.

Upvotes: 5

Cedric Gatay
Cedric Gatay

Reputation: 1583

You're doing it wrong because you set a wicket:id on your <script> part, thus, Wicket will replace it with your Label's content (the javascript function call). Your javascript function is never available because it is never sent to the client. The "good" way of doing what you want is to remove the wicket:id from your script tag and in your behavior use the special method target.appendJavascript("initChannel();"); (or prependJavascript) instead of playing with escaping on a Label.

Please note that your first method may never work if you never "fire" the ajax behavior, the second one should work when the navigator has finished loading the DOM and trigger the "onload" event on your page (but I am not sure the behavior is correctly binded, never tried this...)

An additional note is that the Javascript you wrote is polluting the global namespace of the window, if you consider using this in a real project, please consider reading documentation regarding namespacing of javascript.

Upvotes: 1

Related Questions