Primefaces p:calendar with p:ajax value not updated (one step delay)

Thor picture Thor · Apr 16, 2012 · Viewed 12k times · Source

I want to call a bean after a date is selected in a p:calendar. In my setup I have a @Named @ViewScoped Bean, the class ObWithDate is a @Entity with a date field validFrom.

<h:form id="fUser">
  <p:dataTable id="dt" var="cum" value="#{myBean.listObWithDates}">
    <p:column>
      <p:calendar id="cValidFrom" value="#{cum.validFrom}">  
        <p:ajax event="dateSelect" listener="#{myBean.update(cum)}"
                update=":fUser:dt"/>  
      </p:calendar>  
    </p:column>
  </p:dataTable>
</h:form>

The good thing is, that the bean method update(ObWithDate myO) is called with the correct object each time I select a date. The bad thing is, that myO.validFrom does not have the correct value. It's always one step behind:

  • Field initialized with 2012-01-01
  • GUI change to 2012-01-05, bean method debugs to 2012-01-01
  • GUI change to 2012-01-15, bean method debugs to 2012-01-05

This issue drives me crazy, I've found several issues with not correctly updated values and also some about p:calendar. Most of them suggest using the attribute selectListener="#{calendarBean.handleDateSelect}" with a handleDateSelect(DateSelectEvent event) method. But I want to call my method since I want to pass the current instance of the variable.

  • Firebug verifies, that the correct updated values are transmitted in a POST request
  • I'm using Primefaces 3.2 and JBoss-7.1.1-Final
  • Even without the p:dataTable and only using p:calendar the issue is still the same.
  • The wrong value of the debug output can be observed for the method-Object update(ObWithDate myO) as well for the corresponding entry in myBean.listObWithDates.
  • <p:ajax immediate="true" .../> does not solve this issue.

Update MattHandy helped me a lot, the resulting question How to get the corresponding list item in the ajax call inside the beans method? is formulated in the followup JSF p:calendar in p:dataTable: How to get the row of p:ajax dateSelect event.

Answer

Matt Handy picture Matt Handy · Apr 16, 2012

This is most likely a lifecycle issue. The setter for your field is called before your listener executes. You should not use the listener to set your value.

The el expression on your listener is evaluated at render response phase of the previous request thus it holds the cum value "one step behind".

You should update your custom object from the setter of the calendar's date value.