Reputation: 81
I'm new to facelets and I have generated a project using netbeans but I struggling with the tag.
I have
<h:selectOneMenu id="country" value="#{organisation.organisation.country}" title="Country" >
<f:selectItems value="#{country.countryItemsAvailableSelectOne}"/>
</h:selectOneMenu>
In the select I get classpath.Country[iso=GB] which I can see is an object but I really want to see the the country.prinableName value. I've looked at this for half a day and have drawn a blank Thanks for any help
Upvotes: 2
Views: 6516
Reputation: 1376
If you add editable="true"
in your
<h:selectOneMenu value="#{bean.country}">
Then you'll get an unexpected String
value (not from getAsString()
) in the converter method:
public Object getAsObject(FacesContext context, UIComponent component, String value) { }
Upvotes: 0
Reputation: 1109532
Since you're talking about Facelets, I'll assume JSF 2.x.
To start, HTML is one and all String. JSF generates HTML. By default, non-String
Java objects are by toString()
method converted to their String
representation while JSF generates the HTML. To properly convert between those Java objects and String
, you need a Converter
.
I assume that your Country
object has already the equals()
method properly implemented, otherwise validation will later fail with "Validation error: Value not valid" because the selected object doesn't return true
on testing the equals()
for any of the available items.
I'll also make a little change in the naming since #{country}
is a confusing managed bean name because it does apparently not represent an instance of the Country
class. I'll call it Data
which should hold application wide data.
@ManagedBean
@ApplicaitionScoped
public class Data {
private static final List<Country> COUNTRIES = populateItSomehow();
public List<Country> getCountries() {
return COUNTRIES;
}
// ...
}
I'll assume that the Country
class has two properties code
and name
. I'll assume that the managed bean which receives the selected country has a private Country country
property. In your <f:selectItems>
, you need to loop over #{data.countries}
and specify the country object as item value and the country name as item label.
<h:selectOneMenu value="#{bean.country}">
<f:selectItems value="#{data.countries}" var="country" itemValue="#{country}" itemLabel="#{country.name}" />
</h:selectOneMenu>
Now, you need to create a Converter
for the Country
class. We'll convert based on the country code which is unique for every country (right?). In the getAsString()
you implement code which converts the Java object to its unique String representation which is to be used in HTML. In getAsObject()
you implement code which converts the unique HTML String representation back to the Java object.
@FacesConverter(forClass=Country.class)
public class CountryConverter implements Converter {
@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
return (value instanceof Country) ? ((Country) value).getCode() : null;
}
@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
if (value == null) {
return null;
}
Data data = context.getApplication().evaluateExpressionGet(context, "#{data}", Data.class);
for (Country country : data.getCountries()) {
if (country.getCode().equals(value)) {
return country;
}
}
throw new ConverterException(new FacesMessage(String.format("Cannot convert %s to Country", value)));
}
}
The @FacesConverter
will register it automatically in JSF and JSF will automatically use it whenever it encounters a value expression of the Country
type. Ultimately, you end up with country code as item value and country name as item label. JSF will convert the submitted country code back to a fullworthy Country
object upon form submission.
In JSF 1.x the principle is not much different. In this blog you can find two basic kickoff examples: Objects in h:selectOneMenu
.
Upvotes: 8
Reputation: 8518
What happened to you, selectOneMenu
call the toString()
method for all given objects.
You've to use selectitems
or a simple converter
to manage that. A very simple example:
price.xhtml:
<h:selectOneMenu id="priceMenu" value="#{priceBean.selectedPrice}">
<f:selectItems value="#{priceBean.prices}" />
</h:selectOneMenu>
PriceBean.java:
..
private String selectedPrice;
..
public String getSelectedPrice() {
return selectedPrice;
}
public void setSelectedPrice(String newPrice) {
selectedPrice = newPrice;
}
..
public List<SelectItem> getPrices() {
List<SelectItem> retVal = new ArrayList<SelectItem>();
retVal.add(new SelectItem("2"));
retVal.add(new SelectItem("4"));
retVal.add(new SelectItem("6"));
return retVal;
}
Further informations about the SelectItem
. If you want to use a specially object directly, for example an object called Price
, you have to use a converter. Here an example is shown and here.
Upvotes: 1