Wednesday, December 3, 2008

Creating dropdown lists in JSF: which option to choose?


There are two ways to create dropdown select lists (single selection) in JSF: one with the java.util.Map, another using java.util.List. The following approach shows how to create a dropdown list with Map:

Using Map:

Step 1: In our java class (this can be a managed bean or, a service layer class), we populate a java.util.Map object with POJO that we want to show in the dropdown list. Example below:

First, a CountryVO object which is something like this:






Next, we populate this in the Map:






In line A, we populate the Map with value-against-key, not key-against-value. Although the CountryVO has another property named code, but our obejctive is to show country names in the dropdown list (label), and to fetch country id (value) from the list. We don't want to show country code here. Therefore, to satisfy this with the JSF HtmlSelectOneMenu object, we have to put the label (country name) first and the value (country id) next. This is a pretty weird approach but this is important when we populate the lists in our web pages. I will explain this in the onward sections.


Step 2: In our managed bean, we take an instance of the javax.faces.component.html.HtmlSelectOneMenu and a CountryVO object; and generate accessor methods for it. Example:







In line B, we return the populated Map from the class AnyClass. We could write the getCountries method in this managed bean MyActionBeanClass, instead within the AnyClass class. However, this is just another approach.


Step 3: In our web page (XHTML), we can now populate the dropdown select list like this:







When run, this will generate the following in our web page:




Now, lets recall Line A in Step 1: * countriesMap.put(cvo.getName(), cvo.getIdpk().toString()); *

What would happen if we populated the Map in a key-value pattern, like the following?

countriesMap.put(cvo.getIdpk().toString(), cvo.getName());

Well, in this case, we would get something like this in the web page screen:



Which is not what we expect.

If we view the source in browser, we shall see that it generates the select type input as follows:







Due to this behaviour, we populate a Map with value-key pair rather than a key-value pair.

However, there is another approach for generating selection list, using java.util.List which we shall discuss next:


Using List:

Step 1: In our java class (managed bean or, a service layer class), we populate a java.util.List object with POJO as follows:






[The CountryVO object is unchanged].

Here we initiate a List of javax.faces.model.SelectItem objects and populate it. Please note that in Line C, we populate the List in a key-value pair (unlike we did in Map) .... fair enough! This List
will later be used in our web pages.


Step 2: In our managed bean, we just update method 'getAllCountries' by changing its return type. Rest of the things are same as before. Example follows:







Step 3: In our web page (XHTML), we populate the dropdown select list just as before:


<h:selectOneMenu
binding="#{myActionBean.selectedCountryId}"
value="#{myActionBean.countryVO.idpk}"
id="countryId">
<f:selectItems value="#{myActionBean.allCountries}" />
</h:selectOneMenu>


When run, this will generate and display the similar drop-down list as shown earlier :





In conclusion, I can say that the second approcah is better i.e. using java.util.List. Because a new developer may get confused with the first appraoch. An obvious question might arise: why should we populate the java.util.Map with values against keys instead of key against values.

No comments:

Post a Comment