I would like to set up a Date field in my page like this
|hours| h |minutes|
where hours and minutes are in separated inputText.
The bean have this date
import java.util.Date;
...
private Date myDate;
...
and the page is
<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>
But the problem is that when I submit the form only the last element is saved. For instance if I type the hours and then the minutes, the hours are overwritten and the result is
| 00 | h | minutes |
I tried to set
<h:inputText id="myDateHours" value="#{myBean.myDate.hours}></h:inputText>
<h:inputText id="myDateMinutes" value="#{myBean.myDate.minutes}></h:inputText>
but I get a
Cannot convert 01/01/70 01:00 of type class java.util.Date to int
I don't want to replace my date field with two int field (hours and minutes...) Do you have an idea?
Thanks
This particular case is not possible if you want to use a single model value.
This is however a perfect candidate for a composite component. It allows you to bind a single model value to a group of closely related existing components and perform the processing/conversion in the backing component, fully decoupled from the view and backing bean. One of the examples can be found in this article: composite component with multiple input fields. This example can in for your specific case be altered as follows:
/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;
}
}
Usage:
<html ... xmlns:my="http://java.sun.com/jsf/composite/components">
...
<my:inputTime value="#{bean.date}" />
You need two separate setter methods in the bean, and then do the merge in the server.
<h:inputText id="myDateHours" value="#{myBean.hours}></h:inputText>
<h:inputText id="myDateMinutes" value="#{myBean.minutes}></h:inputText>
Both must get date values, so then you can operate with a JAVA Calendar setting both fields, in the action invoked by your form.
Calendar calendar = new GregorianCalendar();
calendar.setTimeInMillis(0);
calendar.set(Calendar.HOUR, getHours().getHours());
calendar.set(Calendar.MINUTE, getMinutes().getMinutes());
Be aware of time zones if required.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With