Search code examples
jsfprimefaces

Primefaces Calendar when required is true, Ajax listener not invoked


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

Solution

  • 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" />