【问题标题】:Split java.util.Date over two h:inputText fields representing hour and minute with f:convertDateTime用 f:convertDateTime 将 java.util.Date 拆分为两个表示小时和分钟的 h:inputText 字段
【发布时间】:2015-11-01 07:35:23
【问题描述】:

我想像这样在我的页面中设置一个日期字段

|hours| h |minutes|

小时和分钟在分开的 inputText 中。

豆子有这个日期

import java.util.Date;
...
private Date myDate;
...

页面是

<h:form>
    ...
    <h:inputText id="myDateHours" maxlength="2" value="#{myBean.myDate}"
        <f:convertDateTime pattern="HH" />
    </h:inputText>

    <h:outputText value=" h " />

    <h:inputText id="myDateMinutes" maxlength="2" value="#{myBean.myDate}"
        <f:convertDateTime pattern="mm" />
    </h:inputText>
    ...
</h:form>

但问题是,当我提交表单时,只保存了最后一个元素。 例如,如果我输入小时数,然后输入分钟数,小时数将被覆盖,结果为

| 00 | h | minutes |

我试着设置

<h:inputText id="myDateHours" value="#{myBean.myDate.hours}></h:inputText>

<h:inputText id="myDateMinutes" value="#{myBean.myDate.minutes}></h:inputText>

但我得到了一个

Cannot convert 01/01/70 01:00 of type class java.util.Date to int

我不想用两个 int 字段(小时和分钟...)替换我的日期字段 你有什么想法吗?

谢谢

【问题讨论】:

    标签: jsf date input converter


    【解决方案1】:

    如果您想使用单个模型值,则这种特殊情况是不可能的。

    然而,这是composite component 的完美候选者。它允许您将单个模型值绑定到一组密切相关的现有组件,并在支持组件中执行处理/转换,与视图和支持 bean 完全分离。可以在本文中找到其中一个示例:composite component with multiple input fields。此示例可以针对您的具体情况进行如下更改:

    /resources/components/inputTime.xhtml:

    <ui:component
        xmlns="http://www.w3.org/1999/xhtml"
        xmlns:f="http://java.sun.com/jsf/core"
        xmlns:h="http://java.sun.com/jsf/html"
        xmlns:ui="http://java.sun.com/jsf/facelets"
        xmlns:cc="http://java.sun.com/jsf/composite"
    >
        <cc:interface componentType="inputTime">
            <cc:attribute name="value" type="java.util.Date" shortDescription="The selected time. Defaults to now." />
        </cc:interface>
        <cc:implementation>
            <span id="#{cc.clientId}" style="white-space:nowrap">
                <h:inputText id="hour" binding="#{cc.hour}" maxlength="2" converter="javax.faces.Integer" />h
                <h:inputText id="minute" binding="#{cc.minute}" maxlength="2" converter="javax.faces.Integer" />
            </span>
        </cc:implementation>
    </ui:component>
    

    com.example.InputTime

    @FacesComponent("inputTime")
    public class InputTime extends UIInput implements NamingContainer {
    
        private UIInput hour;
        private UIInput minute;
    
        /**
         * As required by <cc:interface>.
         */
        @Override
        public String getFamily() {
            return UINamingContainer.COMPONENT_FAMILY;
        }
    
        /**
         * Set initial hour and minute based on model.
         */
        @Override
        public void encodeBegin(FacesContext context) throws IOException {
            Calendar calendar = Calendar.getInstance();
            Date date = (Date) getValue();
    
            if (date != null) {
                calendar.setTime(date);
            }
    
            hour.setValue(calendar.get(Calendar.HOUR_OF_DAY));
            minute.setValue(calendar.get(Calendar.MINUTE));
            super.encodeBegin(context);
        }
    
        /**
         * Returns the submitted value in HH-mm format.
         */
        @Override
        public Object getSubmittedValue() {
            return hour.getSubmittedValue() + "-" + minute.getSubmittedValue();
        }
    
        /**
         * Converts the submitted value to concrete {@link Date} instance.
         */
        @Override
        protected Object getConvertedValue(FacesContext context, Object submittedValue) {
            try {
                return new SimpleDateFormat("HH-mm").parse((String) submittedValue);
            }
            catch (ParseException e) {
                throw new ConverterException(e);
            }
        }
    
        public UIInput getHour() {
            return hour;
        }
    
        public void setHour(UIInput hour) {
            this.hour = hour;
        }
    
        public UIInput getMinute() {
            return minute;
        }
    
        public void setMinute(UIInput minute) {
            this.minute = minute;
        }
    
    }
    

    用法:

    <html ... xmlns:my="http://java.sun.com/jsf/composite/components">
    ...
    <my:inputTime value="#{bean.date}" />
    

    另见:

    【讨论】:

    • 这是一个很好的解决方案!太感谢了!如果我想更改每个输入的转换器消息,我该怎么办?
    • 用特定的FacesMessage 抛出ConverterException。注意:您不能针对特定输入,两个输入都被视为无效,因为它毕竟是单个组件。
    • 酷!和其他问题,是否可以在输入(组件内部/外部?)上使用模糊 ajax 事件来呈现 h 消息?
    • 是的。如果在里面,只需在每个输入中嵌套&lt;f:ajax event="blur" execute="hour minute" render="messageId"&gt;。如果在外面,只需将输入声明为 &lt;cc:editableValueHolder&gt; 并在其上重新定位 f:ajax
    • 是的,但是如果我的 h 消息在合成器之外,我就无法引用 id。如果我可以像这样在我的页面中添加 ajax 标签会更好 ... 但是没有为合成物定义事件模糊
    【解决方案2】:

    您需要在 bean 中使用两个单独的 setter 方法,然后在服务器中进行合并。

    <h:inputText id="myDateHours" value="#{myBean.hours}></h:inputText>
    <h:inputText id="myDateMinutes" value="#{myBean.minutes}></h:inputText>
    

    两者都必须获取日期值,因此您可以在表单调用的操作中使用 JAVA 日历设置这两个字段。

    Calendar calendar = new GregorianCalendar();
    calendar.setTimeInMillis(0);
    calendar.set(Calendar.HOUR, getHours().getHours());
    calendar.set(Calendar.MINUTE, getMinutes().getMinutes());
    

    如果需要,请注意时区。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多