Super-Easy DropDownChoice Renderer for String values
Too often you may find yourself writing a simple selection list in Wicket.
Whether you know your list values in advance or not, you’ll soon fight with some rendering issue involved with your select component.
Wicket puts at your service the good old DropDownChoice component; good enough to do the job, but it usually force you to use a compound object as its model; If you want to use a simple list of Strings you’ll have to figure out for yourself how to handle “id” and “value” visualization; If not instructed other-way, Wicket will use the “toString” for your object as the display value and its index in the list as its option value.
//DataObject is come kind of value object having the String property "value"...
List<String> values = Arrays.asList( "value_1", "value_2" );
add( new DropDownChoice<String>("my_wicket_id",
new PropertyModel<String>(myDataObject, "value"), values ) );
In the preceding code bit, you’ll get a selection list having options with id=1,2,3.. and displayed values of “value_1″, “value_2″..
If you are happy in using the option index as the actual key and/or you don’t have any localization requirement you can be satisfied with it; Otherwise, here’s a very simple yet effective solution to manage the localization thing and keeping the power to choose what information to use as the option key:
public class StringBasedChoiceRenderer implements IChoiceRenderer<String>{
private static final long serialVersionUID = 1L;
String context;
/**
*
* @param context can be your wicketId or any other string you desire.
* this value is used as a prefix in order to get the localized option value.
*/
public StringBasedChoiceRenderer( String context )
{
this.context = context;
}
/**
* To obtain the display value we localize the string obtained concatenating
* the constructor context value and the actual value of the option.
*/
public Object getDisplayValue(String object)
{
return new ResourceModel( context + "." + object, object ).getObject();
}
/**
* This basic implementation use the entire string value as the option key
*/
public String getIdValue(String object, int index)
{
return object;
}
}
Using this class is super easy:
List<String> values = Arrays.asList( "value_1", "value_2" );
add( new DropDownChoice<String>("my_wicket_id",
new PropertyModel<String>(myDataObject, "value"), values,
new StringBasedChoiceRenderer( "options.value" ) ) );
You’ll have, obviously, to add localization strings to your Application property file. NOTE: you have to put localized strings in your Application-wide property files because the renderes uses ResourceModel and it’s not bound to any component:
options.value.value_1=First Value options.value.value_2=Second Value
Advertisement
Categories: wicket
Just want to say what a great blog you got here!
I’ve been around for quite a lot of time, but finally decided to show my appreciation of your work!
Thumbs up, and keep it going!
Cheers
Christian, iwspo.net
Thanx a lot Christian
I’m really happy to see that this blog is appreciated! thanks again for your support
So how does one associate the picked item from the drop down to a backing bean? So for example you have a bean with a string member. And you want the chosen value (value_1) assigned to the member variable of the pojo bean. Here’s a shortened example:
————————————————————
MyBean myBean = new MyBean();
….
List gendersList = …. from properties file….
DropDownChoice gendersDDC = new DropDownChoice(“gender”, new Model(),
gendersList, new ChoiceRenderer(“value”, “name”));
add(gendersDDC);
————————————————————-
NameValue class is just a pojo with 2 member variables of type String. And myBean has the gender member variable. I assume somehow you assign the model of the bean to the model of the ddc?
In your example, you use an empty Model; in this way there’s no way to connect the DDC with a backing bean.
The point is that you have to make YOUR Pojo the model of the DDC
The Wicket PropertyModel class is there just for this reason; it acts as a proxy/bridge between your model and the DDC, passing back and forth values between the two.
In your code, just substitute the call to “Model()” to :
DropDownChoice gendersDDC = new DropDownChoice(“gender”, new PropertyModel( yourBean, nameOfYourStringProperty ), gendersList, new ChoiceRenderer(“value”, “name”));At this point, the string property of your bean will be used as a source for the selected option in the list (if not null) and the target when the user select an option.
I’m going by memory but It should be right.
Let me know.
You’re correct. I did this last night and it worked:
——————————————————————————
List genders = getStringsList(FormsUtil.get(this, “genders”));
DropDownChoice gendersDDC = new DropDownChoice(“gender”,
new PropertyModel(myBean, “gender”), genders,
new StringBasedChoiceRenderer( “gender” )){
@Override
public boolean isRequired() {
return setRequiredFields;
}
};
gendersDDC.setOutputMarkupId(true);
add(gendersDDC);
——————————————————————————
And in my properties file I have:
gender.M=Male
gender.F=Female
genders=M;F
The trouble I had was what you mentioned but I overlooked. The fact that they need to be in the application properties file. There can’t be enough emphasis on that one!!
Great work and thanks for the help.
I should add that the line: getStringsList(FormsUtil.get(this, “genders”)) should be explained. I don’t want to put the ids of the drop down in the code, so I added them to the props file as : genders=M;F. One method gets them from the props file, and the other splits them into a list to pass to the dropDownChoice.
FormsUtil.get() :
public static String get(Component inst, String key) {
StringResourceModel srm = new StringResourceModel(key, inst, null);
String returnString = srm.getString();
return returnString;
}
and get stringsList:
private List getStringsList(String stringToSplit) {
List strings = new ArrayList();
String[] nameValuesSplit = stringToSplit.split(“;”);
for (int j = 0; j < nameValuesSplit.length; j++) {
strings.add(nameValuesSplit[j]);
}
return strings;
}