JSF表单中的可选日历类型字段

时间:2014-03-12 19:01:55

标签: java jsf jsf-2 calendar

我想在JSF表单中选择一个Calendar输入。当用户没有通知出生时,日历字段必须保持为空。

我的代码:

@Model
public class Registration {
private User user = new User();

    public void register() {
        // stuff
    }
//getUser
}

模型类:

public class User { 
    //other fields
    private Calendar birth;
    // gets and sets
}

页面:

<h:outputLabel for="birth" value="Birth Date" />
<h:inputText id="birth" value="#{registration.user.birth.time}" >
    <f:convertDateTime pattern="dd/MM/yyyy" />
</h:inputText>

到目前为止,此处的问题是<f:convertDateTime>,这取决于getTime() Calendar方法进行转换。它在执行时抛出NPE(空指针异常)。我知道如果我初始化出生问题就解决了,但我真的希望当用户没有填充字段时该字段为空。

有任何关于实现这一目标的想法吗?

2 个答案:

答案 0 :(得分:1)

问题与转换有关,但与表达式无关:

#{registration.user.birth.time}

事实上这是DateTimeConverter代码:

 public Object getAsObject(FacesContext context, UIComponent component,
                          String value) {

    ...

    Object returnValue = null;
    DateFormat parser = null;

    try {

        // If the specified value is null or zero-length, return null
        if (value == null) {
            return (null);
        }
        value = value.trim();
        if (value.length() < 1) {
            return (null);
        }

        ...
         returnValue = parser.parse(value);

     } catch (ParseException e) {
       ...
     }
     return returnValue;
  }

您可以注意到,正确管理null和空值。 但是当应用这些值时,将计算表达式birth.time,但birth引用为空,因此当调用setter on time时,您将获得NPE。

可能的解决方案是直接将birth字段绑定到java.util.Date类型,这是DateTimeConverter管理的类型,如下所示:

public class User { 
    //other fields
    private Date birth;
    // gets and sets
} 

答案 1 :(得分:1)

好吧,我会发布这个给后人。我认为这样做可以做到:

@FacesConverter("CustomCalendarConverter")
public class CalConverter implements Converter{

@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
    if(value != null && !value.toString().isEmpty()){
        try {
            String pattern = (String) component.getAttributes().get("pattern");
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(new SimpleDateFormat(pattern).parse(value));
            return calendar;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    return null;
}

@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {

    if(value != null && !value.toString().isEmpty()){
        Calendar cal = (Calendar) value;
        String pattern = (String) component.getAttributes().get("pattern");
        return new SimpleDateFormat(pattern).format(cal.getTime());
    }
        else return null;
    }
}

视图应该是:

<h:outputLabel for="birth" value="Birth Date" />
<h:inputText id="birth" value="#{registration.user.birth}">
    <f:converter converterId="CustomCalendarConverter" />
    <f:attribute name="pattern" value="dd/MM/yyyy" />
</h:inputText>

您也可以创建复合组件,例如<custom:inputCalendar>