3

以下代码创建了两个单选按钮。每个选项都包含一个日期值,该日期值已成功转换为“yyyy-MM-dd”格式的标签。一旦我做出选择并单击下一步按钮,我会收到以下错误“j_idt12:comDateChoice:验证错误:值无效”。这似乎很简单,但有些不对劲。你们有人能发现吗?

我在 glassfish 中使用 JSF 2.0。

支持豆

public List<SelectItem> getComDateList() {
    List<SelectItem> items = new ArrayList<SelectItem>();
    Calendar cal = GregorianCalendar.getInstance();
    cal.set(Calendar.DAY_OF_MONTH, 1);
    cal.add(Calendar.MONTH, 1);
    Date nextFirst = cal.getTime();
    cal.add(Calendar.MONTH, 1);
    Date followingFirst = cal.getTime();
    items.add(new SelectItem(nextFirst, new SimpleDateFormat("yyyy-MM-dd").format(nextFirst)));
    items.add(new SelectItem(followingFirst, new SimpleDateFormat("yyyy-MM-dd").format(followingFirst)));
    return items;
}

JSF 代码

<h:panelGrid columns="2">
                    <h:outputLabel value="#{msg.FinanceCommencementDate}" for="comDateChoice"/>
                    <h:selectOneRadio id="comDateChoice" value="#{signUpBean.current.commencementDate}" layout="pageDirection">
                        <f:convertDateTime type="date" dateStyle="short"/>
                        <f:selectItems  value="#{signUpBean.comDateList}"/>
                    </h:selectOneRadio>
                </h:panelGrid>
4

1 回答 1

4

如果所选项目值未通过Object#equals()对任何可用选择项目值的检查,则会发生此错误。如果 getter 在表单提交请求的应用请求值阶段返回的列表与在显示表单的初始请求期间返回的列表不同,则会发生这种情况。

因为您在 getter 中重建列表,而不是在视图范围 bean 的构造函数中构造一次,所以对象在每次调用时都会获得不同的时间戳,与初始对象Date相比,它将在未来几分钟/秒Date. 因此equals()意志失败。

将此逻辑移动到 bean 的构造函数中并重写 getter,以便它完成它应该做的事情:只返回 data。不要在 getter 中执行加载逻辑。您还应该将 bean 放在视图范围内,以便在您提交表单时构造函数不会重新运行。

@ManagedBean
@ViewScoped
public class SignUpBean {

    private List<SelectItem> comDateList;

    public SignUpBean() {
        comDateList = new ArrayList<SelectItem>();
        // Fill it here.
    }

    public List<SelectItem> getComDateList() {
        return comDateList; // In getters, do nothing else than returning data!
    }

}

更新:转换器也是问题的潜在根源。您基本上已经指示它在呈现 HTML 页面时去掉时间。所以它在转换回时使用默认时间Date。要么使用

<f:convertDateTime pattern="yyyy-MM-dd HH:mm:ss.SSS Z" />

Calendar或预先重置时间和时区:

cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
cal.setTimeZone(TimeZone.getTimeZone("GMT"));

这样你就可以使用<f:convertDateTime type="date" />

于 2011-03-23T14:49:05.090 回答