Skip to content
ajcamilo edited this page Nov 28, 2014 · 7 revisions

AjaxListSetView

An AjaxListSetView is a repeater that makes it easy to display/work with ListOrderedSets (collection with unique values, but with List order). This repeater is great when you have FormComponents for each row and want to change the list through AJAX, because only new elements of the list are created in the DOM, the rest is just reordered.

You can see a demo here.

How to use

Example using with a table:

<table>
  <tr wicket:id="row">
    <td wicket:id="label">Label</td>
    <td><input type="text" wicket:id="textfield" /></td>
  </tr>
</table
IModel<ListOrderedSet<String>> model = new Model<>(new ListOrderedSet<String>());
AjaxListSetView view = new AjaxListSetView<String>("row", model, "tbody"){
     @Override
      protected void populateItem(ListSetItem<String> item) {
          item.add(new Label("label", item.getModel()));
          item.add(new TextField<String>("textfield", item.getModel()));
      }
});

Very similar to using a ListView. The only difference is the "tbody" tag that's passed in the constructor. It is used to create a DOM element between the table and the tr elements.

Ajax requests

The major difference with this component, is that it supports really well Ajax requests, so when you do target.add(view);, instead of the whole list, only new elements and reordering are sent through. This allows for:

  • small request size.
    • For a collection with 1000 elements, adding an element was an ajax request with ~50KB.
    • Using a ListView the request was ~800KB.
  • loss of data that was not submitted yet.
    • If you have FormComponents on each row and you only add an element to the end of the list, using a ListView, your textfields, checkboxes, etc will be restored to their server state. Even if you use setReuseItems, you still have this problem.
    • Many people to overcome this problem, attach a OnChangeAjaxBehavior, so for every change, each component submits it's data to the server (not good).

You can still send the whole list in the Ajax request if you put it inside a container, for example:

WebMarkupContainer container = new WebMarkupContainer("container");
container.add(view);
...
target.add(container)

Limitations

  • all elements should be comparable

If you use LoadableDetachableModel with data from a database, for example, you should override equals to compare by id

  • placeholder bodyTag

The component needs to create this placeholder between each item and his parent. It can be a div, span, tbody, etc.