JSF 2 - f:selectItems 与日期键映射

Posted

技术标签:

【中文标题】JSF 2 - f:selectItems 与日期键映射【英文标题】:JSF 2 - f:selectItems with a Date keyed Map 【发布时间】:2012-12-12 08:23:04 【问题描述】:

下面的 selectItems 来自 Session Scoped Map。当用户单击提交按钮时,应该在 Request Scoped 支持 bean 中设置一个日期字段并将其显示在页面上。

    <h:selectOneMenu value="#dropDown.selectedDate">
        <f:selectItems value="#mapValues.dateMap.entrySet()" var="entry" itemLabel="#entry.value" itemValue="#entry.key" />
    </h:selectOneMenu>
    <h:commandButton value="Submit" />
You selected Date #dropDown.selectedDate

但是,收到以下转换错误:

Conversion Error setting value 'Wed Dec 26 15:09:32 EST 2012' for 'null Converter'. 

我不确定为什么会收到此错误。我尝试在 selectOneMenu 标记上设置 javax.faces.DateTime 转换器,但随后收到了一个更加神秘的验证错误。

发现a post 建议检查equal() 方法是否可用,并且项目选择是否在下拉列表中,在这种情况下两者都应该是正确的。

我能想到的一种解决方法是将我的地图更改为字符串键控,其中日期保存为字符串。但这似乎是矫枉过正。

关于如何让这个设置工作的任何建议?

支持 bean:

@Named
@RequestScoped
public class DropDown 

    private Date selectedDate;

    public Date getSelectedDate() 
        return selectedDate;
    

    public void setSelectedDate(Date selectedDate) 
        this.selectedDate = selectedDate;
    


地图豆:

@Named
@SessionScoped
public class MapValues implements Serializable 

    private Map<Date, String> dateMap;

    @PostConstruct
    public void init()         
        dateMap = new LinkedHashMap<Date, String>();
        dateMap.put(new Date(), "DATEVALUE1");      
    

    public Map<Date, String> getDateMap() 
        return dateMap;
    

    public void setDateMap(Map<Date, String> dateMap) 
        this.dateMap = dateMap;
    

谢谢!

【问题讨论】:

“但随后收到了一个更加神秘的验证错误。”您为什么不在您的问题中说明它? 它是“form:location: Validation Error: Value is not valid” 【参考方案1】:

使用日期时间转换器应该是正确的解决方案。您的“更神秘的验证错误”原来是这样的:

它是“form:location: Validation Error: Value is not valid

当所选项目的Object#equals() 测试没有针对任何可用项目返回true 时,就会发生这种情况。因此,所选的 Date 与任何可用的 Date 实例都不匹配。

事实上,converter="javax.faces.DateTime"(又名&lt;f:convertDateTime /&gt;)默认忽略时间部分。它默认打印“短”日期样式,如浏览器中的“Dec 27, 2012”右键单击页面,选择查看源代码自己查看。

<option value="Dec 27, 2012">DATEVALUE1</option>

当 JSF 将该格式的字符串提交值转换回具体的 Date 实例时,它基本上变为 2012-12-27 00:00:00.000 而您地图中提供的日期显然仍然设置了时间部分,导致 equals() 始终除非可用日期的地图恰好在 00:00:00.000 午夜巧合生成,否则失败。

这个问题有两种解决方案:

    删除映射中日期的时间部分。您可以为此使用 java.util.Calendar(或者更好的是 Joda Time)。

    改用&lt;f:convertDateTime pattern="yyyyMMddHHmmssSSS"/&gt; 将整个日期/时间转换为最后一毫秒。

    <h:selectOneMenu value="#dropDown.selectedDate">
        <f:selectItems value="#mapValues.dateMap.entrySet()" var="entry" itemLabel="#entry.value" itemValue="#entry.key" />
        <f:convertDateTime pattern="yyyyMMddHHmmssSSS" />
    </h:selectOneMenu>
    

    这样选项值就变成了

    <option value="20121227114627792">DATEVALUE1</option>
    

    当您将 JSF 配置为使用平台特定时区而不是 GMT 作为&lt;f:convertDateTime&gt; 时区时,请注意时区问题。然后,您想将timeZone="UTC" 属性显式添加到转换器。

【讨论】:

第二个解决方案成功了。感谢您的详细解释!

以上是关于JSF 2 - f:selectItems 与日期键映射的主要内容,如果未能解决你的问题,请参考以下文章

JSF-2 f:带有Map的selectItems不显示itemLabel

<f:selectItems> 未在 <h:selectManyListbox> 中呈现

<f:selectItems> 中的对象作为 itemValue [重复]

关于 JSF 2.0 自定义组件和 Primefaces 的帮助

jsf 的日期+时间选择器

在 JSF 中格式化日期输出