Declare a dependency when a script or stylesheet only works after another one is loaded, such as a jQuery plugin or a theme on top of a base stylesheet. Every component that renders the file then gets the library too, in the right order, without knowing about it.
Declare what a reference depends on
Subclass the reference and override getDependencies(). Return header items for what must come first, and keep what the superclass returns:
ChartJs.java
public class ChartJs extends JavaScriptResourceReference {
private static final ChartJs INSTANCE = new ChartJs();
public static ChartJs get() {
return INSTANCE;
}
private ChartJs() {
super(ChartJs.class, "chart.js");
}
@Override
public List<HeaderItem> getDependencies() {
List<HeaderItem> dependencies = super.getDependencies();
dependencies.add(JavaScriptHeaderItem.forReference(ChartCoreJs.get()));
dependencies.add(CssHeaderItem.forReference(ChartCss.get()));
return dependencies;
}
}
A component now renders only the reference it uses:
@Override
public void renderHead(IHeaderResponse response) {
super.renderHead(response);
response.render(JavaScriptHeaderItem.forReference(ChartJs.get()));
}
Wicket renders ChartCoreJs and ChartCss before chart.js, and renders each file once even when several components on the page, or other references, depend on it. Dependencies can have dependencies of their own, and a script can depend on a stylesheet or the other way round. A cycle makes Wicket throw a CircularDependencyException while it renders the page.
Depend on jQuery
For a jQuery plugin, extend JQueryPluginResourceReference. It depends on the jQuery that the application is configured with:
public class DatePickerJs extends JQueryPluginResourceReference {
private static final DatePickerJs INSTANCE = new DatePickerJs();
public static DatePickerJs get() {
return INSTANCE;
}
private DatePickerJs() {
super(DatePickerJs.class, "datepicker.js");
}
}
The jQuery version comes from getJavaScriptLibrarySettings().getJQueryReference(). Point that setting at another reference to use your own copy of jQuery everywhere, including in Wicket’s own components.
Wicket 11 uses jQuery 4 by default; Wicket 10 uses jQuery 3. A plugin that does not work with jQuery 4 can keep jQuery 3 on Wicket 11 with
getJavaScriptLibrarySettings().setJQueryReference(JQueryResourceReference.getV3()).
To depend on Wicket’s own Ajax and event functions, such as Wicket.Event or Wicket.Ajax, add JavaScriptHeaderItem.forReference(getJavaScriptLibrarySettings().getWicketAjaxReference()) to the dependencies; get the settings with Application.get(). That reference follows the application’s choice of library, including the jQuery-free one that Wicket 11 offers, see Run Ajax without jQuery.
Depend on a library from a CDN
UrlResourceReference points to a file on another server. It can declare dependencies like any other reference, and other references can depend on it:
public class JQueryUiJs extends UrlResourceReference {
private static final JQueryUiJs INSTANCE = new JQueryUiJs();
public static JQueryUiJs get() {
return INSTANCE;
}
private JQueryUiJs() {
super(Url.parse("https://code.jquery.com/ui/1.14.1/jquery-ui.min.js"));
}
@Override
public List<HeaderItem> getDependencies() {
List<HeaderItem> dependencies = super.getDependencies();
dependencies.add(JavaScriptHeaderItem.forReference(
Application.get().getJavaScriptLibrarySettings().getJQueryReference()));
return dependencies;
}
}
The default Content Security Policy allows the script because Wicket gives it a nonce, but stylesheets, fonts and images that the library loads from that server need the host in the matching directive, see Configure the Content Security Policy. For subresource integrity, render the item with setIntegrity(…) and setCrossOrigin(CrossOrigin.ANONYMOUS), or set both on the reference.
Give a header item its own dependencies
HeaderItem has the same getDependencies() method. Override it when the dependency belongs to one inline script rather than to a file:
response.render(new OnDomReadyHeaderItem("Chart.draw('" + getMarkupId() + "');") {
@Override
public List<HeaderItem> getDependencies() {
List<HeaderItem> dependencies = super.getDependencies();
dependencies.add(JavaScriptHeaderItem.forReference(ChartJs.get()));
return dependencies;
}
});
Wicket renders the dependencies first and the ready script after all files, as described in Control the order of header items.