0
votes

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.

2

2 Answers

2
votes

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);
}
0
votes

First of all: f:ajax doesn't have an update attribute, in f:ajax you need to use the render attribute.

A p:remoteCommand with the ajax oncomplete Attribute should solve the problem:

<p:outputPanel id="fl83">
<p:remoteCommand name="updateCalendar" update="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}"
                oncomplete="updateCalendar()" />
            <p:ajax event="dateSelect" listener="#{filtroFechasBB.fechaInicioClickChange}"
                oncomplete="updateCalendar()" />
        </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}"
                oncomplete="updateCalendar()" />
            <p:ajax event="dateSelect" listener="#{filtroFechasBB.fechaFinClickChange}"
                oncomplete="updateCalendar()" />
        </p:calendar>
    </p:outputPanel>
</p:outputPanel>

If that doesn't solve the problem: do you've a form around it which modifies the ids? If you've a without prependId="false" form1 is prepend to every id inside the form. So you'd need to access the panel with exampleForm:fl83.