Custom components

You already have seen some Wicket components in action. You also learned that you can influence what the components actually do by providing them with proper models. Now it is time to look at how to customize Wicket components.

Extending

Usually you do not want to start from scratch when you customize a component. Most components can be extended, and have methods that are explicitly meant for customization.

Some components do not even work without this, like wicket.markup.html.link.Link, which has abstract method onClick(), or wicket.markup.html.list.ListView that has abstract method populateItem().

Component wicket.markup.html.form.DropDownChoice is a non-abstract component, but by extending it, we can alter its behaviour. For example, look at:

add(new DropDownChoice("venueSelect",
                        new PropertyModel(this, "currentVenue"), getVenueDao().findVenues())
{
  protected boolean wantOnSelectionChangedNotifications()
  {
    return true;
  }
});

By overloading method wantOnSelectionChangedNotifications(), and have it return true (instead of false which is the default), an onchange javascript event handler will be generated, so that on each new selection of the dropdown, a roundtrip will be made to the server, updating the model of the dropdown component. And if you used your models smart enough, this can have the effect that other components have an updated rendering as well.

And if we want to customize the component even further, we could do:

add(new DropDownChoice("venueSelect",
                       new PropertyModel(this, "currentVenue"), getVenueDao().findVenues())
{
  protected boolean wantOnSelectionChangedNotifications()
  {
    return true;
  }

  protected void onSelectionChanged(Object newSelection)
  {
    // do something here...
  }
});

and do something nice in the onSelectionChanged() event handler.

By making use of models that use e.g. a shared property, we can do all kinds of neat things. Here is an example:

add(new DropDownChoice("venueSelect",
                       new PropertyModel(this, "currentVenue"), getVenueDao().findVenues())
{
  protected boolean wantOnSelectionChangedNotifications()
  {
    return true;
  }
});
WebMarkupContainer container = new WebMarkupContainer("rolesListContainer")
{
  public boolean isVisible()
  {
    return getCurrentVenue() != null;
  }
};
add(container);

Note that we fed our dropdown with a property model that works on this (e.g. a Page) using property 'currentVenue'.  Now, with the second component we override method isVisible, and use that same property 'currentVenue' for our evaluation.
If any venue is selected, we'll display the container and anything that is nested on it. If no venue is selected, we do not display anything. This is a very handy trick to switch parts of your page on and off, and as the dropdown will generate a roundtrip on each selection, our page will feel very dynamic.

TODO... write more

AttributeModifiers

TODO

Panels and Borders

See also Panels and borders to see the difference between Panels and Borders.

Both Panels and Borders have their own markup file, but the markup is used in different ways:

The Border component inserts markup before and after its child components.

<html>
    <body>
     <div wicket:id="myBorder">
      <!-- Border markup -->
      <span wicket:id="myContent">content</span>
      <!-- Border markup -->
     </div>
    </body>
   </html>

The Panel component inserts markup into the body of the tag.

<html>
    <body>
     <div wicket:id="myPanel">
      <!-- Panel markup -->
     </div>
    </body>
   </html>

See Panel for more information.

Doing it (almost) from scratch

TODO

  • No labels