3
votes

I have two panels in Wicket.

ParentPanel and ChildPanel

Scenario

ChildPanel is a component of ParentPanel. Every time a certain event is fired in the Parent panel, I want to prepend a certain javascript in the ChildPanel.

Working Solution

ParentPanel.java

public class ParentPanel extends Panel
{
    private static final long serialVersionUID = 4306746527837380863L;
    private final ChildPanel childPanel;

    public ParentPanel(String aId, IModel<AnnotatorState> aModel)
    {
        super(aId);
        model = aModel;

        // initially the Child panel is empty. passing empty model
        childPanel = new ChildPanel("child-container", Model.of());
        childPanel.setOutputMarkupId(true);
        add(childPanel);
    }

    @OnEvent
    public void onClickText(RenderEvent aEvent)
    {
        LOG.trace("Event Fired");
        IPartialPageRequestHandler iPartialPageRequestHandler = aEvent.getRequestHandler();

        Integer someData = getSomeData();
        childPanel.setDefaultModel(Model.of(someData));

        //I am trying to add the child panel to the ajax target to ensure rerendering of child panel.
        iPartialPageRequestHandler.add(childPanel);
    }
}

ChildPanel.java

public class ChildPanel extends Panel
{
    private static final long serialVersionUID = -3849226240909011148L;
    private static final Logger LOG = LoggerFactory.getLogger(ChildPanel.class);
    private IModel<Integer> model;

    public ChildPanel(String aId, IModel<Integer> aModel)
    {
        super(aId);
        model = (aModel);
    }

    @Override
    public void renderHead(IHeaderResponse aResponse)
    {
        super.renderHead(aResponse);
        model = (IModel<Integer>) getDefaultModel();

        if (model == null)
            return;
        Integer someData = model.getObject();
        String someJavascript = createSomeJavascript(someData);

        log.debug("Rendering Updated UI with the JS: ", javascript);
        aResponse.render(OnDomReadyHeaderItem.forScript(javascript));
    }
}

Apparently renderHead() is called every time the childPanel is added to the iPartialPageRequestHandler and it does my work that is to update the UI on every event fired in the ParentPanel.

Problem

However I have been told that this is not a good practice. Since in this case, the JS is added to renderHead(), then it ends up in the page source code - that gets cumbersome when sending (large) JSON data. A good place to attach the JS to the AJAX target needs to be found (maybe render() or probable better onRender() or onAfterRender()) only if its possible/doable in Wicket. Due to my limited knowledge, I am not able to guess how else I can implement the scenario. Any other (better or possible) solution is welcomes and appreciable.

Thanks.

1
What you're currently doing is adding a HeaderItem (i.e. a snippet that gets placed in the <head>) on each render. If, what you want to do instead is to execute a certain piece of JS before/after adding the component but no more, then you should look at the methods IPartialPageRequestHandler.prependJavaScript and IPartialPageRequestHandler.appendJavaScript. - Jeroen Steenbeeke
I have explored these methods. But I can only use them if I have an ajax target object. Which leads me to question, in which function should I prepend the javascript so that it is called everytime the child panel is added to the request handler. I try to implement the onRender or onAfterRender method but I am not able to get an ajaxTarget or iPartialPageRequestHandler which I can use to call the prependJavaScript method. - Sibgha
Then again, I'm not sure if those exist in Wicket 1.5.x or 6.x (which you tagged), though they definitely exist in Wicket 7.x and 8.x - Jeroen Steenbeeke
Yes these methods exist but can I access the IPartialPageRequestHandler object in onRender() so that I can call prependJavascript in that function? - Sibgha

1 Answers

1
votes

I assume the problem is that the createSomeJavascript creates a big chuck of code?

I would then refactor it so that createSomeJavascript just calls a function that you add to the Component using a JavaScriptResourceReference. This way, only a small bit of Javascript ends up in the source.

For example, put your javascript in an external file like this:

private static final ResourceReference  JS_QM   = new JavaScriptResourceReference( ClientPanel.class, "question.mark.js" );


@Override
public void renderHead( Component component, IHeaderResponse response )
{
    super.renderHead( component, response );
    response.render( JavaScriptReferenceHeaderItem.forReference( JS_QM, "question-mark" ) );
    ...
}