Got a bit stuck while working on a JSF Custom Component. Would be nice if someone could give me head start.
The idea is to have a component that lets me page through a LocalDate
. Think of a simpler date picker. The rendered HTML has two buttons, one to increment the date by a day and another button to decrement the date by a day. The value itself is stored in a input hidden. Attached is a simple version of the component which doesn't work, but hopefully describes what I am trying to achieve.
The idea is to have say <my:datePager value="#{myBackingBean.someDate}" />
on a page and execute some logic/action once one of either button has been clicked.
For example <my:datePager value="#{myBackingBean.someDate} action="..." />
or <my:datePager value="#{myBackingBean.someDate} previous="..." next="..."/>
No idea what is better.
Here is what I am stuck with: How to call the previous
and next
methods on the component?
This is my JSF 2.3 custom component so far:
@FacesComponent(LocalDatePager.COMPONENT_TYPE)
public class LocalDatePager extends UIInput {
public static final String COMPONENT_TYPE = "LocalDatePager";
public LocalDatePager() {
setConverter(LocalDateConverter.INSTANCE);
}
public void previous() {
LocalDate localDate = (LocalDate) getValue();
localDate = localDate.minusDays(1);
setValue(localDate);
}
public void next() {
LocalDate localDate = (LocalDate) getValue();
localDate = localDate.plusDays(1);
setValue(localDate);
}
@Override
public void decode(FacesContext context) {
super.decode(context);
}
@Override
public void encodeEnd(FacesContext context) throws IOException {
ResponseWriter writer = context.getResponseWriter();
writer.startElement("div", this);
writer.writeAttribute("class", "btn-group", null);
writer.writeAttribute("role", "group", null);
writer.startElement("button", this);
writer.writeAttribute("type", "button", null);
writer.writeAttribute("class", "btn btn-outline-primary", null);
writer.writeText("Previous", null);
writer.endElement("button");
writer.startElement("button", this);
writer.writeAttribute("type", "button", null);
writer.writeAttribute("class", "btn btn-outline-primary", null);
writer.writeText("Next", null);
writer.endElement("button");
writer.endElement("div");
writer.startElement("input", this);
writer.writeAttribute("name", getClientId(context), "clientId");
writer.writeAttribute("type", "hidden", null);
writer.writeAttribute("value", getValue(), "value");
writer.endElement("input");
}
}
From my understanding the component I have is mind is both UIInput
and UICommand
. Do I need to implement ActionEvent
? Fire value change events?
At the moment I do the whole previous and next methods in backing beans and not in a component. This leads to lots of duplicate code and I thought a custom component fits best. I tried to work with Composite Components, but this did not get me far either.
Another approach so far has been client behaviour: execute JavaScript, change the value of the hidden input and submit the form. This felt even worse.
Would be nice if someone could give me a pointer in the right direction.