1

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.

Community
  • 1
  • 1
Thor
  • 6,607
  • 13
  • 62
  • 96
  • Note that `@Named` and `@ViewScoped` don't work together. CDI doesn't know a view scope. Maybe this is not the reason of your concrete problem but may cause undesired behavior now or later. – Matt Handy Apr 16 '12 at 13:52
  • @MattHandy: I'm using Seam which enhances CDI with this scope (http://docs.jboss.org/seam/3/faces/latest/reference/en-US/html/scopes.html#viewscoped), this works like a charm on several pages. It's _one step behind_, not _one day behind_. I update the question to clarify this. – Thor Apr 16 '12 at 14:08
  • This must be a lifecycle issue. The method setter is called _before_ the listener executes. And the listener sets the value back to the previous value. – Matt Handy Apr 16 '12 at 15:35
  • Yes, but how to solve it? I also tried `p:ajax immediate="true"`without success. – Thor Apr 16 '12 at 15:38
  • I had similar issue wtih `datatable` and `calendar` - used for filtering. Try to add `widgetVar` to your `datatable` and call ajax like this : `` . Although I've updated the table with `update` I needed to force update once more - mentioned lifecycle problem. IMO you have to force update once more too. – Fallup Apr 16 '12 at 16:43

2 Answers2

3

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.

Matt Handy
  • 29,855
  • 2
  • 89
  • 112
  • If I understand you correct I should not use `myBean.update(cum)` but only `myBean.update`. By doing this I still expect that the `cum` in `listObWithDates` is set during the ajax request and I have actual values in the beans `update()` method. But there are the _old_ ones, too. – Thor Apr 16 '12 at 18:03
  • For a better understanding: What is your update method actually doing? Why do you need to call it? – Matt Handy Apr 16 '12 at 19:50
  • The update method should directly update the changed date value in the database. – Thor Apr 17 '12 at 05:08
  • Then you should set the date value with the setter (will automatically be set with ajax) and only persist/merge the (already set) data in the listener. – Matt Handy Apr 17 '12 at 05:58
  • The listener is now only a `public void update()`. The problem is still, that the correct value is not "already set" while inside this method. (See my first comment to your answer) – Thor Apr 17 '12 at 06:14
  • It would be available in `event` if you use a select listener as described in your question with `handleDateSelect(DateSelectEvent event)`. Or is the concrete problem that you don't know the datatable row where the listener was called from? – Matt Handy Apr 17 '12 at 10:45
  • Yes, I think that's the reason why I tried it to pass the object itself to the listener. – Thor Apr 17 '12 at 12:05
1

I ran into this issue today morning. Found that primefaces have removed the DateSelectEvent from Primefaces 3.5 . Hence had to remove the ajax event call from my calendar object. Instead retrieving the value using get..(). Please find the discussion for the same in this link below. http://forum.primefaces.org/viewtopic.php?f=3&t=27590

Sabarish
  • 862
  • 1
  • 14
  • 23