【问题标题】:F:selectItems showing the class not a valueF:selectItems 显示类不是值
【发布时间】:2011-09-08 19:05:54
【问题描述】:

我是 facelets 的新手,我已经使用 netbeans 生成了一个项目,但我在使用标签时遇到了困难。

我有

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

在选择中,我得到了 classpath.Country[iso=GB],我可以看到它是一个对象,但我真的很想看到 country.prinableName 的值。 我看了半天,画了一个空白 感谢您的帮助

【问题讨论】:

    标签: jsf


    【解决方案1】:

    既然您在谈论 Facelets,我将假设 JSF 2.x。

    首先,HTML 是一个完整的字符串。 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 属性。在您的&lt;f:selectItems&gt; 中,您需要遍历#{data.countries} 并将国家对象指定为项目值,将国家名称指定为项目标签。

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

    现在,您需要为 Country 类创建一个 Converter。我们将根据每个国家/地区唯一的国家/地区代码进行转换(对吗?)。在getAsString() 中,您实现了将Java 对象转换为要在HTML 中使用的唯一字符串表示形式的代码。在getAsObject() 中,您实现了将唯一的 HTML 字符串表示形式转换回 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 中自动注册它,并且 JSF 将在遇到 Country 类型的值表达式时自动使用它。最终,您最终将国家代码作为项目值,将国家名称作为项目标签。 JSF 将在提交表单时将提交的国家代码转换回完整的Country 对象。

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

    【讨论】:

    • 谢谢你所有的假设都是正确的,一个很好的解释将通过这个例子来帮助我在其他地方也有帮助
    【解决方案2】:

    发生了什么事,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 shownand here.

    【讨论】:

      【解决方案3】:

      如果你在你的

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

      那么你会在转换器方法中得到一个意想不到的String 值(不是来自getAsString()):

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

      【讨论】:

        猜你喜欢
        • 2012-05-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-12-14
        • 1970-01-01
        • 1970-01-01
        • 2015-05-29
        相关资源
        最近更新 更多