F:selectItems显示类不是值

时间:2011-09-08 19:05:55

标签: jsf

我是facelets的新手,我使用netbeans生成了一个项目,但是我在标签上苦苦挣扎。

我有

<h:selectOneMenu id="country" value="#{organisation.organisation.country}" title="Country" >
                <f:selectItems value="#{country.countryItemsAvailableSelectOne}"/>
            </h:selectOneMenu>

在select I get classpath.Country [iso = GB]中,我可以看到它是一个对象,但我真的想看到country.prinableName值。 我已经看了半天,并且画了一个空白 谢谢你的帮助

3 个答案:

答案 0 :(得分:7)

既然你在谈论Facelets,我会假设JSF 2.x。

首先,HTML是一个和所有String。 JSF生成HTML。默认情况下,非String Java对象通过toString()方法转换为其String表示,而JSF生成HTML。要在这些Java对象和String之间正确转换,您需要Converter

我假设您的Country对象已经有equals()方法properly implemented,否则稍后验证会因“验证错误:值无效”而失败,因为所选对象不会返回true正在测试任何可用项目的equals()

我还会对命名进行一些更改,因为#{country}是一个令人困惑的托管bean名称,因为它显然不代表Country类的实例。我将其称为Data,它应该包含应用程序范围的数据。

@ManagedBean
@ApplicaitionScoped
public class Data {

    private static final List<Country> COUNTRIES = populateItSomehow();

    public List<Country> getCountries() {
        return COUNTRIES;
    }

    // ...
}

我假设Country类有两个属性codename。我假设接收所选国家/地区的托管bean具有private Country country属性。在<f:selectItems>中,您需要循环#{data.countries}并将国家/地区对象指定为项目值,将国家/地区名称指定为项目标签。

<h:selectOneMenu value="#{bean.country}">
    <f:selectItems value="#{data.countries}" var="country" itemValue="#{country}" itemLabel="#{country.name}" />
</h:selectOneMenu>

现在,您需要为Converter课程创建Country。我们将根据每个国家/地区唯一的国家/地区代码进行转换(对吗?)。在getAsString()中,您实现了将Java对象转换为其在HTML中使用的唯一String表示的代码。在getAsObject()中,您实现了将唯一HTML String表示形式转换回Java对象的代码。

@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)));
    }

}

@FacesConverter将在JSF中自动注册它,只要遇到Country类型的值表达式,JSF就会自动使用它。最终,您最终将国家/地区代码作为项目值,将国家/地区名称作为项目标签。在提交表单时,JSF会将提交的国家/地区代码转换回完整的Country对象。

在JSF 1.x中,原则并没有太大的不同。在本博客中,您可以找到两个基本的启动示例:Objects in h:selectOneMenu

答案 1 :(得分:0)

发生了什么事,selectOneMenu为所有给定对象调用toString()方法。

您必须使用selectitems或简单的converter来管理它。一个非常简单的例子:

<强> 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;
}

有关SelectItem的更多信息。如果要直接使用特殊对象,例如名为Price的对象,则必须使用转换器。 Here an example is shown and here

答案 2 :(得分:0)

如果您在

中添加editable="true"
<h:selectOneMenu value="#{bean.country}">

然后您会在转换器方法中获得意外的String值(不是来自getAsString()):

public Object getAsObject(FacesContext context, UIComponent component, String value) { }