user2529173
user2529173

Reputation: 1924

Call Wicket Code from Javascript

I'm trying to call some Java code from Javascript in Wicket.

This is my Java code:

public ShowUnternehmen() {

    add(new AbstractDefaultAjaxBehavior() {
        @Override
        protected void respond(AjaxRequestTarget ajaxRequestTarget) {
            System.out.println("respond");
        }

        @Override
        public void renderHead(Component component, IHeaderResponse response) {
            super.renderHead( component, response );
            System.out.println(getCallbackUrl());
        }
    });

}

And this is the Javascript code:

<wicket:head>
    <script type="text/javascript" >
        $(function() {
            $.contextMenu({
                selector: '.context-menu-one',
                callback: function(key, options) {
                    var m = "clicked: " + key;
                    alert("BLA");
                    Wicket.Ajax.get({"u":"./com.emg.panels.unternehmen.ShowUnternehmen?1-1.IBehaviorListener.0-"})
                },
                items: {
                    "edit": {name: "Editieren", icon: "edit"},
                    "quit": {name: "Abbrechen", icon: function(){
                        return 'context-menu-icon context-menu-icon-quit';
                    }}
                }
            });

            $('.context-menu-one').on('click', function(e){
                console.log('clicked', this);
            })
        });
    </script>
</wicket:head>

But the response method is never executed. I was looking at other examples but they all seem to be confusing.

I got this url from renderHead method

Upvotes: 3

Views: 4293

Answers (2)

Markus Hettich
Markus Hettich

Reputation: 574

You are on a good way. It would be more relalible if you let wicket render the callback function to the page. The following two examples show how you can do that:

A) Render a global callback function. The disadvantage will be that you will have only one callback endpoint.

(1) Create a behavior like the following one:

public class CallFromJavascriptBehavior extends AbstractDefaultAjaxBehavior {
@Override
protected void respond(AjaxRequestTarget target) {
    final StringValue parameterValue = RequestCycle.get().getRequest().getQueryParameters().getParameterValue("yourName");
    System.out.println(String.format("Hello %s", parameterValue.toString()));
}

@Override
public void renderHead(Component component, IHeaderResponse response) {
    super.renderHead(component, response);
    response.render(JavaScriptHeaderItem.forScript(String.format("nameOfFunction=%s", getCallbackFunction(CallbackParameter.explicit("yourName"))), "CallFromJavascriptBehavior"));
}}

(2) Add this behavior to your wicket page.

(3) Now you can call nameOfFunction('Markus'); from your javascript.

B) Call a initialisation function for each instance of your component on page.

(1) add a initialisation function to your page

<script>
    function initMyComponent(selector, callback){
        $(selector).click(function(){
            callback("Markus");
        });
    }
</script>

(2) Create a behavior like the following which calls the initialisation function and passes the necessary selector and callback function.

public class ComponentBehavior extends AbstractDefaultAjaxBehavior{
@Override
protected void respond(AjaxRequestTarget target) {
    final StringValue parameterValue = RequestCycle.get().getRequest().getQueryParameters().getParameterValue("yourName");
    System.out.println(String.format("Hello %s", parameterValue.toString()));
}

@Override
public void renderHead(Component component, IHeaderResponse response) {
    super.renderHead(component, response);
    response.render(OnDomReadyHeaderItem.forScript(String.format("initMyComponent('#%s', %s)", component.getMarkupId(), getCallbackFunction(CallbackParameter.explicit("yourName")))));
}}

(3) Add the behavior to your wicket component.

If the response method did not get called this could have different reasons. You should check your console (ide and browser) first.

Upvotes: 6

user6073886
user6073886

Reputation:

An easy way to trigger java/wicket code from Javascript is to use a hidden input with an event behavior as a hook.

Hidden inputs are form elements that are "invisible" but can be quite usefull for cases like this.

Setup Wicket components

First we add a HiddenField on our Wicket page and give it an AjaxEventBehavior

final HiddenField<Void> hiddenInput = new HiddenField<>("hiddenInput");
add(hiddenInput);
hiddenInput.add(new AjaxEventBehavior("change") {

    @Override
    protected void onEvent(final AjaxRequestTarget target) {
        // Execute any code you like and respond with an ajax response 
        target.appendJavaScript("alert('Hidden Input Change Event Behaviour!');");
        }
});

I used that Javascript alert as an example because a System.out.println might be ignored by some logger systems. I also used the change event, although others would probably work as well.

The corresponding HTML-Markup:

<input type="hidden" wicket:id="hiddenInput" id="hiddenInput1"/>

NOTE: I gave the input a fixed id value. Since ids should be unique on every page you couldn't make this into a Wicket Panel and add it multiple times to a page. You would have to let wicket create the ids (setOutputMarkupId(true)) and then find a way to pass the ids to your javascript. But for this very simple example this should suffice.

Trigger with Javascript

Now all you need to do is trigger a change event on your hidden input and it will execute the code you defined in the onEvent method.

With JQuery and the id, this is extremly simple:

<script>
    $('#hiddenInput1').change();
</script>

Hope this simple example helps you to get the idea. As i already said in my comments this is only really usefull when your javascript call doesn't need/care about the response and you just want to be able to trigger wicket code from JavaScript.

Upvotes: 2

Related Questions