GitHub

User guideAjax and JavaScript

Update components with Ajax

Re-render components, show hidden ones, refresh lists and run JavaScript in response to an Ajax request.

How-toWicket 10 and later

Use this when an Ajax callback has changed some state and the browser should show the result without reloading the page. Every Ajax callback receives an AjaxRequestTarget; what you add to it is rendered again and sent back. For what happens underneath, see How Wicket Ajax works.

Re-render a component

Give the component a markup id when you create it, change its state in the callback and add it to the target:

HomePage.java

public class HomePage extends WebPage {
    private int clicks;

    public HomePage() {
        Label counter = new Label("counter", () -> clicks);
        counter.setOutputMarkupId(true);
        add(counter);

        add(new AjaxLink<Void>("increment") {
            @Override
            public void onClick(AjaxRequestTarget target) {
                clicks++;
                target.add(counter);
            }
        });
    }
}

HomePage.html

<p>Clicked <span wicket:id="counter"></span> times.</p>
<a wicket:id="increment">Click me</a>

target.add takes any number of components. The markup id must be there from the first render: without setOutputMarkupId(true) the browser has no element to replace, and the browser console shows “Component with id … was not found while trying to perform markup update”. See Give a component a markup id for the ways to set one.

Show a component that was hidden

An invisible component renders nothing, so there is nothing to replace. Call setOutputMarkupPlaceholderTag(true) to make it leave an empty, hidden tag with its id:

Label message = new Label("message", "Saved.") {
    @Override
    protected void onConfigure() {
        super.onConfigure();
        setVisible(saved);
    }
};
message.setOutputMarkupPlaceholderTag(true);
add(message);

add(new AjaxLink<Void>("save") {
    @Override
    public void onClick(AjaxRequestTarget target) {
        saved = true;
        target.add(message);
    }
});

The placeholder tag implies a markup id. Use it on every component that you hide or show through Ajax, and on a container whose visibility depends on its children. Show, hide or disable a component covers onConfigure.

Refresh a list or table

Repeaters such as ListView, RepeatingView and DataView have no tag of their own, and target.add throws an IllegalArgumentException for them. Wrap the repeater in a container and add the container:

TodoPage.html

<ul wicket:id="items">
    <li wicket:id="item"><span wicket:id="title"></span></li>
</ul>

TodoPage.java

WebMarkupContainer items = new WebMarkupContainer("items");
items.setOutputMarkupId(true);
add(items);

items.add(new ListView<>("item", todos) {
    @Override
    protected void populateItem(ListItem<Todo> item) {
        item.add(new Label("title", item.getModel().map(Todo::getTitle)));
    }
});

// in the callback
target.add(items);

For tables with paging and sorting, the Ajax variants in Ajax components refresh themselves. A whole page can be added too, target.add(getPage()); Wicket then redirects the browser to the page instead of sending a partial update.

Run JavaScript after the update

appendJavaScript runs a script after the components are replaced, prependJavaScript before:

target.add(counter);
target.appendJavaScript("document.getElementById('" + counter.getMarkupId() + "').scrollIntoView();");

Never put user input into the script without escaping it; Wicket sends the string as it is. To move the keyboard focus, use target.focusComponent(component), which needs the component’s markup id as well.

Let a component refresh itself

When a component should be refreshed after every Ajax request on the page, for example a FeedbackPanel or a header with a shopping cart, let it add itself. Wicket sends the AjaxRequestTarget as an event to every component on the page before it responds:

public class CartSummary extends Panel {
    public CartSummary(String id) {
        super(id);
        setOutputMarkupId(true);
        // ...
    }

    @Override
    public void onEvent(IEvent<?> event) {
        super.onEvent(event);
        if (event.getPayload() instanceof AjaxRequestTarget target) {
            target.add(this);
        }
    }
}

Code outside a callback, such as a service method that only has the component, can find the target of the current request with RequestCycle.get().find(AjaxRequestTarget.class), which returns an Optional that is empty for a normal request. Events between components are covered in Send events between components.