Wicket – How to replace a panel with Ajax

Today I’d like to deal with a common problem in wicket application. How to replace dinamically a panel. Let’s start…

The problem:
You have a Radio Choice with two buttons, when you click on the first button, the panel1  is diplayed, when you click on the second one, the panel2 is displayed in place of the last one and so on…

The solution: I write two different html files for the two panels: panel1.html and panel2.html.

<wicket:panel>
 this is the panel 1
 </wicket:panel>
<wicket:panel>
 this is the panel 2
 </wicket:panel>

The java class for each panel looks like this:

public class Panel1 extends Panel{
    public Panel2(String id) {
       super(id);
       //write other code here...
    }
}

Now we can start with the parent component wich will contain the panels and the radio component.
The parent component can be a Page or another panel. For this example it is a wicket page. Here is the html code:

<html>
    <head>
        <title>Replace Panel example</title>
    </head>
    <body>
        <form wicket:id="form">
          <span wicket:id="rChoice"></span>
          <span wicket:id="replacedPanel"></span>
        </form>
    </body>
</html>

Under the tag form we have two components, the radio choice and a panel. This panel will be replaced each time the user changes the radio selection.

To do that using Ajax, we have to attach a behaviour to the radio choice component.
Let’s take a look at the java code…

public class HomePage extends WebPage {
    private Panel replacedPanel;
    public HomePage(final PageParameters parameters) {
        List<String> choices = new ArrayList<String>();
        choices.add("panel1");
        choices.add("panel2");
        final RadioChoice<String> rChoice = new RadioChoice<String>("rChoice");
        rChoice.setModel(new Model<String>(selectedPanel));
        rChoice.setChoices(choices);
        rChoice.add(new AjaxFormChoiceComponentUpdatingBehavior() {
              @Override
              protected void onUpdate(AjaxRequestTarget target) {
                  Panel newPanel = null;
                  if ("panel1".equals(rChoice.getModelObject())){
                      newPanel = new Panel1("replacedPanel");
                  }else{
                      newPanel = new Panel2("replacedPanel");
                  }
                  newPanel.setOutputMarkupId(true);
                  replacedPanel.replaceWith(newPanel);
                  target.addComponent(newPanel);
                  replacedPanel = newPanel;  
              }
        });
        //this shows the panel1 when you load for the first time the page
        replacedPanel = new Panel1("replacedPanel");
        replacedPanel.setOutputMarkupId(true);
        Form<String> form = new Form<String>("form");
        form.add(rChoice);
        form.add(replacedPanel);
        this.add(form);       
    }
}

Finished!
As you can see, the most important thing is that the two panels should have the same id (in this case is replacedPanel).
This is a general example, maybe the way to create the panels in the onUpdate method is not elegant but it’s out of scope from this example.

That’s all for now.
Carmine