0

For a new project we are using a complex external JavaScript library which needs some parameters for initialization. This parameter values are only known at runtime and therefore we wanted to build some sort of AJAX mechanism for the JavaScript to load the parameters when needed.

I tried to achieve this by the following mechanisms:

PageThatContainsTheJavaScript.java

public GraphPanel(String id) {
  add(new AbstractDefaultAjaxBehavior() {
    protected void respond(final AjaxRequestTarget target) {
        final RequestCycle requestCycle = RequestCycle.get();           
        TextRequestHandler textRequestHandler = new TextRequestHandler("text/plain", "UTF-8", content.toString()); //content - the parameter value
        requestCycle.scheduleRequestHandlerAfterCurrent(textRequestHandler);
    }
  });
  add(new Label("ajaxtest", ""));
}
@Override
protected void onBeforeRender() {
  super.onBeforeRender();
  String callbackUrl = behave.getCallbackUrl().toString();
  String callbackFunction = String.format("Wicket.Ajax.get({'u':'%s'});",callbackUrl);
  replace(new Label("ajaxtest", callbackFunction));
}

The label "ajaxtest" is just a way to conveniently access the generated callback url for testing purposes.

PageThatContainsTheJavaScript.html

function externalApplicationStart() {
  var parameter = Wicket.Ajax.get({'u':"'"+document.getElementById('ajaxtest').innerHTML+"'"});
  var application = new demo.yfiles.layout.modules.LayoutModulesDemo(parameter);
  // arbitrary init code
  application.start();
});

I didn't find a really good tutorial on this issues, so it is possible, that there is something wrong with that attempt, although I guess that the overall direction is correct.

My problem is, that as long as the Wicket.ajax.get line is present, the JavaScript function hangs. When I comment the line and pass a hardcoded default parameter, the application starts. What am I doing wrong and how can I get the String parameter from Wicket to the JavaScript function?

A functional solution I found is passing the parameter value as content of a hidden HTML tag (like <span id='...' style='display:none;'>parameterValue</span>), but in the future it might be neccessary to pass even longer values to the JavaScript (like XML content) and I don't want to mess the generated HTML up with all those non-content-values.

//edit: The generated ajaxtest-HTML-Tag looks like this:

<span wicket:id="ajaxtest" id="ajaxtest">
  Wicket.Ajax.get({'u':'./.?0-1.IBehaviorListener.0-graphContainer-graphControl'});
</span>

Trying to execute Wicket.Ajax.get({'u':'./.?0-1.IBehaviorListener.0-graphContainer-graphControl'}); in the console only results in undefined.

Also I am not sure where that second dot in the URL comes from (./.?0...), but trying the same with ./?0... results in the same.

2 Answers 2

2

In your GraphPanel i would override renderHead() and initialize your parameters there and alson start your JS component there like this:

@Override
public void renderHead(IHeaderResponse response) {
    super.renderHead(response); 
    response.render(OnDomReadyHeaderItem.forScript("var parameter = 'aaa';"));
    response.render(OnDomReadyHeaderItem.forScript("externalApplicationStart();"));
}

A full solution in my mind would in renderHead also load your js lib and a js file that contains function to control your js lib. Something like this:

@Override
public void renderHead(IHeaderResponse response) {
    super.renderHead(response); 
    response.render(OnDomReadyHeaderItem.forScript("var parameter = 'aaa';"));
    response.render(JavaScriptReferenceHeaderItem.forReference(yourJsLibResourceReference));
    response.render(JavaScriptReferenceHeaderItem.forReference(yourJsToControlTheJsLib));
    response.render(OnDomReadyHeaderItem.forScript("externalApplicationStart();"));
}
Sign up to request clarification or add additional context in comments.

5 Comments

This looks indeed like a much more clean solution than using some invisible HTML tags for passing stuff around. But still it puts everything in the generated HTML file - like I said, the configuration parameters are only known at runtime so I can't prepare a JavaScript file to import. For passing a single parameter the renderHead option seems fine. But like I said, in the future it is very likely that this one parameter becomes substantially longer and more complicated - in this case I would really prefer passing it on demand.
Dont tell me that you want to generate a file dynamically that would contain all parameters. Ok, you can do it like you say but i think it would make or complicated to understand why you generate a file instead of directly setting the var's.
Because the library is generally built to read the config from xml files. It's just our use case that we can't provide them at build time - and I thought just passing the content via AJAX would be cleaner than to write a temporary file on the server and make sure that resource is accessible to the library. I know it's not nice but using another library is no option due to compatibility issues.
You can generate and XML file on the fly as a Resource and mount it. Read wicketguide.comsysto.com/guide/chapter14.html#chapter14_6 and the next chapter. Otherwise i would go with my renderHead answer.
Very nice tutorial, strange I didn't find it myself yet. I guess that covered every open issue (for now), thanks :)
0

You can add a custom javascript event onto an HTML element and invoke it from your javascript by trigger see http://www.w3schools.com/jquery/event_trigger.asp or use jQuery.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.