How do I force a Primefaces calendar to update after a change Ajax event validates the new value?

El Suscriptor Justiciero picture El Suscriptor Justiciero · Sep 19, 2016 · Viewed 11.7k times · Source

I'm modifying a page with two Calendar components, to select a start date and an end date. I'm supposed to make them check that the start date is before the end date whenever you modify either of them; if the start is set after the end or viceversa, the code changes the end date to the maximum date and pops a warning.

The event listeners run correctly, but the end date calendar fails to update to reflect the new value; it's not that it updates before the listener changes the value ─it fails to update at all.

The project runs on Primefaces 5.3 and Java 1.6. This is the xhtml (minus styles for readability):

<p:outputPanel id="fl83">
    <p:outputPanel id="fl83c3">
        <h:outputLabel value="Start date" for="fechaInicioMP" />
        <p:calendar locale="es" pattern="dd/MM/yyyy" id="fechaInicioMP"
            maxdate="#{filtroFechasBB.fechaMaxFin}" value="#{filtroFechasBB.fechaInicio}"
            onSelectUpdate=":f183" >
            <p:ajax event="blur" />
            <f:ajax event="change" listener="#{filtroFechasBB.fechaInicioTextChange}"
                render="@this" update="@form" />
            <p:ajax event="dateSelect" listener="#{filtroFechasBB.fechaInicioClickChange}"
                update="@form" />
        </p:calendar>
    </p:outputPanel>
    <p:outputPanel id="fl83c4">
        <h:outputLabel value="End date" for="fechaFinMP" />
        <p:calendar locale="es" pattern="dd/MM/yyyy" id="fechaFinMP"
            maxdate="#{filtroFechasBB.fechaMaxFin}" value="#{filtroFechasBB.fechaFin}"
            onSelectUpdate=":f183" >
            <p:ajax event="blur" />
            <f:ajax event="change" listener="#{filtroFechasBB.fechaFinTextChange}"
                render="@this" update=":fl83" />
            <p:ajax event="dateSelect" listener="#{filtroFechasBB.fechaFinClickChange}"
                update=":fl83" />
        </p:calendar>
    </p:outputPanel>
</p:outputPanel>

And these are the listeners:

    public void fechaFinTextChange() {
    if(fechaFin.after(fechaMaxFin)) {
        fechaFin = fechaMaxFin;
        addErrorMessage(FFIN_AFTER_FMAX);
    }
    compareInicioBeforeFin();
}

public void fechaFinClickChange(SelectEvent event) {
    setFechaFin((Date)event.getObject()); // I couldn't find out why this is here given that
                                          // the setter has already been called
    compareInicioBeforeFin();
    if (updateMetodoEntreBB != null) {
        ajaxActualiza(event, OpcionesAjax.F_FIN);
    }
}

// fechaInicioTextChange and fechaInicioClickChange do pretty much the same as these two

private void compareInicioBeforeFin() {
    if(fechaInicio.after(fechaFin)) {
        fechaFin = fechaMaxFin;
        addErrorMessage(FINI_AFTER_FFIN);
    }
}

There are two Ajax events because the JSF change event doesn't trigger when you click on the calendar and the PrimeFaces dateSelect doesn't trigger when you type a date in.

I've tried the onSelectUpdate from the calendar and the render and update from both ajax events, setting them to @this, @form, the end date calendar's ID, both calendars' IDs, the calendar's outputPanel's ID and the common outputPanel's ID, and the damn calendars just. Won't Update.

I'm at my wits' end and my Google Fu doesn't find any solution that works either.

Answer

Bilal Dekar picture Bilal Dekar · Sep 19, 2016

You need to set an ajax event on the click of the start date calendar :

<p:calendar id="start_date" pattern="dd/MM/yyyy HH:mm"  value="#{managedBean.startDate}"  size="20" >
    <p:ajax event="dateSelect" listener="#{managedBean.OnSelectDate()}" update=":form:end_date" />
</p:calendar>   

<p:calendar id="end_date"  pattern="dd/MM/yyyy HH:mm" mindate="#{managedBean.startDate}"  value="#{managedBean.endDate}"  size="20" /> 

When you select the startDate that triggers a method where you set endDate to null, and you update the endDate calendar, which is limited by mindate="#{managedBean.startDate}"

public void OnSelectDateSouhaite() {
    this.setEndDate(null);
}