【问题标题】:Value of selected item from SelectOneMenu does not get set in converterSelectOneMenu 中选定项目的值未在转换器中设置
【发布时间】:2013-02-10 23:56:09
【问题描述】:

在一个 JSF 项目中,我有一个由字符串值列表填充的 SelectOneMenu,并连接到一个整数值“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();
            }
        }
    }
}

【问题讨论】:

  • 看来问题出在getAsString 方法中。尝试在那里调试并检查它为什么落在!(value instanceof Integer) 条件下(提示:你有一个List&lt;String&gt;,而不是List&lt;Integer&gt;)。

标签: jsf converter selectonemenu


【解决方案1】:

您没有提供转换器期望的物品。

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

您有一个List&lt;String&gt; 作为可用的项目值。因此,当每个项目都将要呈现为 HTML 时,它会通过getAsString()。但是,您正在执行instanceof Integer 检查,它总是会失败并因此为每个项目返回null。所以你最终会在生成的 HTML 中得到一个无价值的&lt;option&gt;,它会以null 提交。这就是为什么你的getAsObject() 最终会得到nulls。

根据目前的尝试,我的印象是#{applicantController.yearStart} 实际上是您想要设置年份的Integer,如果选择了“1990 年之前”,则为-1。如果您想保留转换器,则应将可用项目更改为

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

【讨论】:

  • 解释得很好。这帮助我了解了实际情况。谢谢
【解决方案2】:

我知道这可能是解决方案。 您应该将列表和选定元素存储在属性中,并在使用组件时将它们维护在范围内。

【讨论】:

  • OP 已经为此使用了@ApplicationScoped。因此,这绝对不是 OP 特定问题的原因。
  • 信不信由你,我在类似的情况下删除了 equals 和 hashcode 并且它起作用了。然后我决定使用 DTO 而不是真实对象来维护我的实体哈希码和等号。但我的 dto 只有所需的属性 + 可序列化的实现。终于成功了。
  • 你的方法完全有缺陷,相信我。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-21
  • 2012-10-03
  • 2021-05-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多