SelectOneMenu中所选项目的值未在转换器中设置

时间:2013-02-10 23:56:09

标签: jsf converter selectonemenu

在JSF项目中,我有一个由字符串值列表填充的SelectOneMenu,并连接到Integer值“yearStart”。 当我从列表中选择一个值时,转换器总是输出到控制台“stringVal = null”。 为什么所选项目的值不能转换为转换器?

我的网页包含以下内容:

<h:selectOneMenu value="#{applicantController.yearStart}">
    <f:selectItems value="#{yearList.years}" />
    <f:converter converterId="studyYearConverter"/>
</h:selectOneMenu>

它使用这个年份列表:

@ManagedBean
@ApplicationScoped
public class YearList implements Serializable {

    private static final long serialVersionUID = 1L;

    private final List<String> years = Arrays.asList("prior to 1990", "1990",
        "1991", "1992", "1993", "1994", "1995", "1996", "1997", "1998",
        "1999", "2000", "2001", "2002", "2003", "2004", "2005", "2006",
        "2007", "2008", "2009", "2010", "2011", "2012", "2013");

    public List<String> getYears() {
        return years;
    }

}

我的转换器类:

@FacesConverter(value = "studyYearConverter")
public class StudyYearConverter implements Converter {

    private static final String PRIOR_TO_1990 = "prior to 1990";

    @Override
    public Object getAsObject(FacesContext context, UIComponent component,
            String stringVal) {
        if (PRIOR_TO_1990.equals(stringVal)) {
            return -1;
        } else {
            System.out.println("stringVal = " + stringVal);  
            // Why is this alway null??
            try {
                return Integer.parseInt(stringVal);
            } catch (NumberFormatException pe) {
                FacesMessage message = new FacesMessage(
                       "Invalid date format. Valid format e.g. 2010-04");
                throw new ConverterException(message);
            }
        }
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component,
        Object value) {
        if (value == null || !(value instanceof Integer)) {
                return null;
        } else {
            Integer year = (Integer) value;
            if (year == -1) {
                return PRIOR_TO_1990;
            } else {
                return year.toString();
            }
        }
    }
}

2 个答案:

答案 0 :(得分:0)

您没有提供转换器所需的物品。

在呈现HTML响应期间使用getAsString()方法。此时,(可能)复杂的Java对象需要转换为其唯一的String表示,以便它们可以用HTML表示。在应用HTTP请求参数值期间使用getAsObject()方法。 HTTP请求参数值可以像HTML输入值一样只表示为String,为了获得复杂的Java对象,必须转换唯一的String表示。

您有List<String>个可用的项目值。因此,当每个项目即将呈现为HTML时,它将通过getAsString()。但是,您正在执行instanceof Integer检查,该检查始终会失败,因此会为每个项目返回null。因此,您最终会在生成的HTML中获得无价值的<option>,并以null的形式提交。这就是为什么getAsObject()最终得到null的原因。

根据到目前为止的尝试,我的印象是#{applicantController.yearStart}实际上是Integer,您想要用年份设置,或-1 if“1990之前“被选中。如果您想保留转换器,那么您应该将可用项目更改为

private final List<Integer> years = Arrays.asList(-1, 1990,
        1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
        1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
        2007, 2008, 2009, 2010, 2011, 2012, 2013);

答案 1 :(得分:-1)

我知道哪个可能是解决方案。 您应该将列表和所选元素存储在属性中,并且只要使用该组件,就将它们保留在范围内。