Welcome to the 55 Minutes blog.
55 Minutes is a web development consultancy in San Francisco building apps for design-led businesses and startups. On this blog we discuss the technology tools of our trade: Ruby on Rails, Django, Sass, OS X, and more.
How to Implement Radio Buttons in Wicket
By Matt on
Oct 25, 2011
Implementing radio buttons in a Wicket form is one of the more challenging tasks for developers new to the framework. But setting aside Wicket, even getting the HTML itself right is nontrivial. Let’s take a look at how this is done, starting with the HTML.
A first cut at the HTML might look like this:
That renders fine, but there is a subtle usability issue: clicking on Apple, Google or Microsoft doesn’t toggle the appropriate radio button. A well-designed form should do this. Furthermore, br tags are a sign that we are inappropriately mixing styling instructions into our markup. We can do better.
What we’ve done here is used appropriate semantic markup to give the browser more information. The browser now sees that Apple, Google, and Microsoft are actually labels for the radio buttons AAPL, GOOG, and MSFT, respectively. When you click the label, the browser automatically toggles the appropriate radio button. Much better.
Finally, we sprinkle on some CSS to ensure each radio button is rendered on a separate line.
Wicket: Static Choices
In a web application you’ll probably deal with two different sets of radio buttons: static radio buttons have the choices hardcoded in the HTML, like we’ve done in the example above; dynamic radio buttons have choices that come from the database. Let’s look at the simpler static case first.
Wicket handles radio buttons using a pair of classes: Radio and RadioGroup. Each radio button is represented by a Radio component; in turn, those Radio components must all be contained in a single RadioGroup. All of these components need to have a corresponding wicket:id in the HTML.
By default, the RadioGroup tag is not rendered. It just serves as a container to hold a group of Radio components. We’ll use Wicket’s wicket:container tag for this purpose, rather than insert a meaningless div or span into our markup.
Notice that we’ve removed the value attributes from the input tags. Wicket will manage them for us.
Our corresponding Java code looks like this:
What’s important to note here is that each Radio component has a model. In Wicket, you don’t have direct access to the POST data being sent to the browser; you only have access to the Radio model. When the form is submitted, Wicket does the following:
Based on the POST data, Wicket determines which Radio component was selected by the user.
Wicket reads the model value associated with the selected Radio component.
Wicket passes this value to the model of the RadioGroup component.
In short: you use models on the Radio components to tell Wicket about the possible values, and the model on the RadioGroup is the user’s chosen value. You’ll see that these basic rules apply to the dynamic case as well.
Wicket: Dynamic Choices
Most of the time we don’t know the values of the radio buttons ahead of time; we don’t necessarily even know how many there will be. Furthermore, each radio button will have a unique identifier and label. How do we generate the HTML and wire up Wicket with this dynamic data?
First we need a way to represent each choice that comes from the database. Let’s assume we have a simple value object for this purpose.
Our basic approach will be as follows:
Ask the database for a list of Company objects.
Loop over those objects and create a Radio for each one.
We’ll use Company.symbol to uniquely identify each choice, and Company.name as the display value.
Here’s our HTML:
The choice section of the markup will be repeated for each choice. For each choice we’ll provide a radio button and a label.
This does almost everything we want. If you run this code and view the resulting HTML in the web browser, you’ll notice that Wicket is generating meaningless incremental identifiers for each of the radio buttons, like this:
Ideally we want Wicket to use our own unique identifier, Company.symbol, as the value. You can do this by overriding Radio.getValue(), but this is a bit tedious.
Instead, consider using the RadioChoicesListView component in our very own fiftyfive-wicket library. This component captures all the best practices described in this article, handles overriding Radio.getValue() and helpfully eliminates some of the boilerplate code. The more concise solution is thus: