Blog

Wicket and List Choice Transfers

25 Mar, 2008
Xebia Background Header Wave

Consider the following scenario: we want to have two select boxes and we want to add options from one to the other and back.
Currently, this is not easily possible in Wicket, even though there are a lot of extensions available.
This blog describes an easy way to create a component which does just that!

select transfer select transfer

For creating a Select box there are multiple options available. You can use a ListChoice for selecting a single option or a ListMultipleChoice for selecting multiple options.
So how do we start?
Well, first we need to create two ListMultipleChoice object. Lets give them the following names: originals and destinations
As you can see below, this isn’t very hard.

  // The Selected options in the list choices.
  private List selectedOriginals;
  private List selectedDestinations;
ListMultipleChoice originals = new ListMultipleChoice("originals",
  new PropertyModel(this, "selectedOriginals"), new LoadableDetachableModel() {
      @Override
      protected Object load() {
        return Arrays.asList(new String[] {"one", "two", "three", "four", "five", "six"});
      }
    });
ListMultipleChoice destinations = new ListMultipleChoice("destinations",
   new PropertyModel(this, "selectedDestinations"), new LoadableDetachableModel() {
      @Override
      protected Object load() {
        return new ArrayList();
      }
    });

and the matching HTML part:


Next we need two buttons, one for adding and one for removing options from a select box.

AjaxButton add = new AjaxButton("add") {
      @Override
      protected void onSubmit(AjaxRequestTarget target, Form form) {
            update(target,selectedOriginals, originals, destinations);
      }
    };
AjaxButton remove = new AjaxButton("remove") {
       @Override
      protected void onSubmit(AjaxRequestTarget target, Form form) {
           update(target, selectedDestinations, destinations, originals);
      }
    };
  /**
   * Updates the select boxes.
   * @param target The {@link AjaxRequestTarget}.
   */
  private void update(AjaxRequestTarget target, List selections, ListMultipleChoice from, ListMultipleChoice to) {
    for (String destination : selections) {
      List choices = getChoices(from);
      if (!to.getChoices().contains(destination)) {
        to.getChoices().add(destination);
        choices.remove(destination);
        from.setChoices(choices);
      }
    }
    target.addComponent(to);
    target.addComponent(from);
  }

and the matching HTML part:


As you can see I use an AjaxButton, which is basically what you want for this example. We do not want to do a full page reload.
That’s it.
Next thing we want to do is create a component that does all of this, so we can reuse it. After analysing, I found out that we only need a method which retrieves all options. I have called it getOriginalChoices();
If you look into the attached example project, you can see that it is now very easy to use it.
To use the Component you need to do the following:

    ListMultipleChoiceTransfer listMultipleChoiceTransfer = new ListMultipleChoiceTransfer("test"){
      @Override
      public List getOriginalChoices() {
        return Arrays.asList(new String[] {"one", "two", "three", "four", "five", "six"});
      }
    };

and the matching html

ListMultipleChoiceTransfer will be placed here

I have attached the example project here so you can look into the code yourself.

Questions?

Get in touch with us to learn more about the subject and related solutions

Explore related posts