我想在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(空指针异常)。我知道如果我初始化出生问题就解决了,但我真的希望当用户没有填充字段时该字段为空。
有任何关于实现这一目标的想法吗?
答案 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>
。