7

In my application I have three dropdown menu (p:selectOneMenu), say A, B, C. Among them two are dependent, say B and C. By changing the value of B I am dynamically loading values to C. Also there is a textbox. The value of the textbox is generating by ajax when the on-change event is firing from these three dropdowns.

Here is the xhtml:

<p:selectOneMenu id="customerMenu" value="#{adminController.activityDTO.customerId}" required="true" label="Customer Name" style="width: 200px">
    <f:selectItem itemLabel="Select One" itemValue="" />
    <f:selectItems value="#{adminController.customers}" var="customer" itemLabel="#{customer.customerName}" itemValue="#{customer.customerId}" />
    <p:ajax listener="#{adminController.generateActivityName}" update="activityId" />                       
</p:selectOneMenu>

<p:selectOneMenu id="activityTypeMenu" value="#{adminController.activityDTO.activityParentType}" required="true" label="Activity Type"
    style="width: 200px">
    <f:selectItem itemLabel="Select One" itemValue="" />
    <f:selectItems value="#{adminController.activityTypes}" var="activityType" itemLabel="#{activityType.parent}" itemValue="#{activityType.parent}" />
    <p:ajax listener="#{adminController.updateDependentActivity}" update="activitySubType" />
</p:selectOneMenu>

<p:selectOneMenu id="activitySubTypeMenu" value="#{adminController.activityDTO.activitySubType}" required="true" label="Activity Sub Type"
    style="width: 200px">
    <f:selectItem itemLabel="Select One" itemValue="" />
    <f:selectItems value="#{adminController.activitySubTypes}" var="activityType" itemLabel="#{activityType.name}" itemValue="#{activityType.id}" />
    <p:ajax listener="#{adminController.generateActivityId}" update="activityId" />
</p:selectOneMenu>

<p:inputText id="activityId" autocomplete="off" readonly="true" value="#{adminController.activityDTO.activityId}"
    label="#{adbBundle['admin.addActivityPanel.addActivityTable.activityId']}" required="true" />

The activityTypeMenu and activitySubTypeMenu are dependent, by the selected value of the activityTypeMenu I am populating the activitySubTypeMenu.

Now the problems that I am facing is:

  • Say I have select "External" and "Internal" in activityTypeMenu and default "Select One". If I choose "External" from activityTypeMenu the activitySubTypeMenu will have "Project" and "Service". But then if I choose the default "Select One" the activitySubTypeMenu is still holding the previously dynamically populated values. This is because the required="true" attribute resisting to fire the backend method from which I am loading the dynamic value.
  • I have tried to set the itemValue of <f:selectItem itemLabel="Select One" itemValue="" /> to #{null} and then the backend method is firing on selecting the "Select one" option and I can set an empty list to activitySubTypes and this way the activitySubTypeMenu get empty. But in that case the required="true" is getting meaningless. I mean, I also have save button and on clicking that button without selecting any option (that is selecting "Select one") from activityTypeMenu and activitySubTypeMenu not throwing ValidatorException and the components are not getting styled by the error css class of Primefaces.
  • Also if I don't set the itemValue of <f:selectItem itemLabel="Select One" itemValue="" /> to #{null} then on-changing to selected value to default option("Select one") does not clearing out the activityId p:inputText. If I use #{null} then I can get the backend method firing from which I can set the value of the textbox to empty.

How ca i solve this issues and get desired result. What I want are:

  • If the option is set to "Select one" then the dependent menu will be empty and that of the textbox.
  • I want to use the required="true" attribute.
tshepang
  • 12,111
  • 21
  • 91
  • 136
Tapas Bose
  • 28,796
  • 74
  • 215
  • 331
  • Have you tried with `process="@this"` attribute in `p:ajax` tags? That avoids the validation of other form components, because only the component you're changing is processed by the JSF lifecycle. If not working, the easiest (but not best) way to get it work would be getting rid of `required="true"` attributes and validate the whole form entirely when it's sent. Good luck. – Aritz Jan 26 '13 at 15:11
  • However I think already `p:ajax` defaults to `@this`. – Aritz Jan 26 '13 at 15:17
  • @XtremeBiker, yes the `p:ajax` default value is `@this` – Tapas Bose Jan 26 '13 at 15:34
  • Try to use the `noSelectionOption="true"` flag on your ``. It is a reserved flag that causes the runtime to evaluate your selection differently. – kolossus Jan 26 '13 at 18:16
  • @kolossus according to http://code.google.com/p/primefaces/issues/detail?id=4582 it has bug with `noSelectionOption`. – Tapas Bose Jan 26 '13 at 20:16

1 Answers1

10

You can use EL in the required attribute. You can let the desired expression evaluate true only when a particular submit button is pressed, or when a particular component value is submitted (and thus by its client ID present in the request parameter map #{param}).

The following kickoff example should do what you need.

<p:selectOneMenu binding="#{menu1}" ... required="#{not empty param[submit.clientId]}">
    ...                       
</p:selectOneMenu>
<p:selectOneMenu ... required="#{not empty param[menu1.clientId]}">
    ...                       
</p:selectOneMenu>
<p:commandButton binding="#{submit}" ... />

This way, the 1st menu is only required when the form's main submit button is pressed (and thus not when event listeners are fired) and the 2nd menu is only required when the 1st menu has a value.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • 1
    Do you have a full working example of that technique? Either BalusC or the OP (who marked it as the accepted answer). I added the bindings and changed my requireds but the 2nd menu still has a validation error. – Rasshu Jun 04 '14 at 17:58