Change CSS on AJAX request in Wicket throws exception in dev mode

47 views Asked by At

This is a follow-up of Change CSS on AJAX request in Wicket.

I implemented the possibility to change CSS on an AJAX request by making the <style> a proper Wicket component. This is used inside my container component (FontContainerComponent) as follows:

<wicket:head>
  <style wicket:id="css"></style>
</wicket:head>

The model of this CSS label (read: the content of my CSS) is added like this:

@Override
protected void onBeforeRender() {
  String fontCss = someProvider.getFontCss();
  addOrReplace(new Label("css", fontCss));
  super.onBeforeRender();
}

This is added to the Ajax update inside another component's onClick method:

@Override
public void onClick(AjaxRequestTarget target) {
  // Irrelevant code left out here...
  target.add(getFontContainer());
}

This worked fine in Wicket 7. I've now upgraded my code to Wicket 9 and now an exception is being thrown when my container component is added to an AjaxRequestTarget. It still works fine when the page is initially rendered. The exception only appears in development mode also appeared in Wicket 8.

The exception comes from Page::checkRendering, which thinks that the style label (id = css) is not added to the response:

org.apache.wicket.WicketRuntimeException: The component(s) below failed to render. Possible reasons could be that:
    1) you have added a component in code but forgot to reference it in the markup (thus the component will never be rendered),
    2) if your components were added in a parent container then make sure the markup for the child container includes them in <wicket:extend>.

1. [Component id = css, page = com.example.component.page.MyPage, path = fontContainerComponent:css, type = org.apache.wicket.markup.html.basic.Label, isVisible = true, isVersioned = true]

So, my questions are:

  1. What did change from Wicket 7 to Wicket 8, that causes the exception to happen in this scenario?
  2. What can I do to fix it?

For 2: Obviously, I could turn off the check (application.getDebugSettings().setComponentUseCheck(false)) or use the different approach from the original question (render the CSS not as a label, but using renderHead and then use JavaScript code to remove previously added CSS in each AJAX update), but I'm searching for a solution using my current approach (if possible).

1

There are 1 answers

2
martin-g On

I think the problem is in the usage of <wicket:head>. It does its magic (logic) to move the inner HTML to the <head> of the page and somehow breaks the Wicket Component tree.

IMO it would be better to re-work your code to use header contribution:

@Override
public void renderHead(IHeaderResponse response) {
  super.renderHead(response);
  response.render(CssHeaderItem.forCSS("...", "my-generated-styles"));
}

my-generated-styles will be used as an element id for the <style> element, so Ajax repaints will replace its body.