2

Intro- I have 2 p:calendar components, calreq has required="true" while calnotreq is optional.

Code- p:calendar xhtml code with ajax calls

<p:outputLabel value="Calendar Required" for="calreq" />
<p:calendar label="Calendar Required" id="calreq" 
    required="true"
    inputStyle="width: 100px;" showOn="button"
    value="#{myBean.calReqObj}" >
    <p:ajax event="dateSelect" listener="#{myAction.calReqChange()}"/>
    <p:ajax event="change" listener="#{myAction.calReqChange()}"/>
</p:calendar>

<p:outputLabel value="Calendar Not Required" for="calnotreq" />
<p:calendar label="Calendar Not Required" id="calnotreq" 
    inputStyle="width: 100px;" showOn="button"
    value="#{myBean.calNotReqObj}" >
    <p:ajax event="dateSelect" listener="#{myAction.calNotReqChange()}"/>
    <p:ajax event="change" listener="#{myAction.calNotReqChange()}"/>
</p:calendar>

Listener implementations

//Invoked everytime **calreq** changes, except for null case
public void calReqChange() {
    //myBeanObj
    System.out.println("getCalReqObj from ajax event: " + myBeanObj.getCalReqObj() );
}   

//Invoked everytime **calnotreq** changes, including for null case
public void calNotReqChange() {
    //myBeanObj
    System.out.println("getCalNotReqObj from ajax event: " + myBeanObj.getCalNotReqObj() );
}

Description- It's part of a big chunk of code & is wrapped properly inside form/panel/panelgrid. Both the ajax calls calReqChange() & calNotReqChange() are invoked when date value is changed, either from calendar or keyboard.

Problem- calreq's ajax listener is not invoked under one scenario. When the date field is emptied/nullified, the listeners are not called & correspondingly backing bean object is not updated to null. (But calnotreq listeners are invoked)

What's the reason & How to resolve this?

Note-

  1. I experimented with different properties inside p:ajax, but nothing helps: immediate=true, process=@this, update=@this. Also tried f:ajax instead of p:ajax.
  2. For the required p:calendar component, the asterisk(*) symbol is needed in label for look & feel purpose. Like this: enter image description here
8
  • 'ajax' is central to this post. Not sure why 'ajax' tag was removed. Commented May 24 at 7:36
  • 1
    That's is expected behavior. See also item #3 of stackoverflow.com/q/2118656. Why exactly do you want action methods to be invoked on validation failure? It sounds like those shouldn't be ajax listener methods in first place. I.e. you have an XY-problem. You'll need to take a step back and explain the actual problem in detail for which you incorrectly thought that using an ajax listener method would be the right solution. Then we can propose the correct solution.
    – BalusC
    Commented May 26 at 15:10
  • @BalusC- Requirement is that, everytime p:calendar value changes, the server side myBean.calReqOb should also be immediately updated (not wait for commandbutton submit). That's why I included the listeners. No logic inside listeners, but when listener is invoked, bean object setters are automatically called. Commented May 26 at 15:45
  • Further on the requirement, there's another set of p:selectBooleanCheckbox & p:calendar id="dependentCal". When Checkbox is enabled, dependentCal should pick current value from p:calendar id="calreq". That's why I added ajax listeners, as it updates myBean.calReqObj immediately. To keep my post simple, I didn't add this piece of code. Commented May 26 at 15:59
  • 1
    Then this is your solution: stackoverflow.com/q/14729982
    – BalusC
    Commented May 26 at 16:03

1 Answer 1

3
+50

As per the question's comments you appear to need action-dependent validation. So the calendar should only be validated as required when a specific action is invoked, which is the main command button action, not the ajax listener action.

This can be solved as per the guidelines found in the related question: Validate input as required only if certain command button is pressed.

<p:calendar ... required="#{param.containsKey(mainCommandButton.clientId)}">
    <p:ajax ... />
</p:calendar>
...
<p:commandButton binding="#{mainCommandButton}" ... />

And, in order to retain the 'required asterisk' of the associated <p:outputLabel>, simply set its indicateRequired attribute to true. It will otherwise default to auto and only be applied when the UIInput#isRequired() of the associated input component returns true during render response phase.

<p:outputLabel ... indicateRequired="true" />
6
  • It will take me sometime to test, but ideally this should work. So accepting this as Answer. Will confirm once my testing is complete. Commented May 26 at 17:52
  • Will this binding happen if ajax="false" is set on commandButton? <p:commandButton ajax="false" binding="#{mainCommandButton}" ... /> Commented May 31 at 11:09
  • 1
    Of course. Please note that above code is as-is. I.e do absolutely not bind it to a bean property. See also stackoverflow.com/q/14911158 Do note that the linked related question contains an alternative solution without the need to use binding: a hardcoded client ID.
    – BalusC
    Commented May 31 at 11:33
  • Yes, I tried it as mentioned, without binding to bean property. But still the validation is not happening on cmdbutton submit. I have updated the code section. Can you have a look? Not sure what I'm missing. Commented May 31 at 12:56
  • 1
    You might have uncovered a PrimeFaces bug/quirk. The button's request parameter is present, but has unexpectedly an empty value when ajax=false instead of ajax=true. I've updated the answer.
    – BalusC
    Commented May 31 at 14:07

Not the answer you're looking for? Browse other questions tagged or ask your own question.