1

In testing the validateOrder validator in OmniFaces 1.8.1, it seems that the validator is not applied to components when used in conjunction with a Primefaces commandButton that partially submits components based on a PrimeFaces Selector (PFS). A sample is below, which is a stripped-down, but representative, test case of my app's usage.

<h:body>
    <h:form>
        <p:commandButton value="Show" action="#{testBean.save}" oncomplete="PF('testDialogJS').show()"/>
    </h:form>

    <p:dialog header="Test Dialog" widgetVar="testDialogJS" resizable="false" closeOnEscape="false" closable="false" modal="true" dynamic="true">
        <h:form>
            <p:tabView>
                <p:tab title="Tab 1">
                    <p:panel header="Tab 1 Panel" styleClass="tab1Panel">
                        <p:outputLabel value="Test 1"/>
                    </p:panel>
                </p:tab>
                <p:tab title="Tab 2">
                    <p:panel header="Tab 2 Panel" styleClass="tab2Panel">
                        <h:panelGrid columns="2">
                            <p:outputLabel for="startDate" value="Start Date: "/>
                            <h:panelGroup>
                                <p:calendar id="startDate" value="#{testBean.startDate}" navigator="true" pattern="M/d/yyyy"
                                            required="true" requiredMessage="Start Date is required"/>
                                <p:message for="startDate"/>
                            </h:panelGroup>

                            <p:outputLabel for="endDate" value="End Date: "/>
                            <h:panelGroup>
                                <p:calendar id="endDate" value="#{testBean.endDate}" navigator="true" pattern="M/d/yyyy"
                                            required="true" requiredMessage="End Date is required"/>
                                <p:message for="endDate"/>

                                <o:validateOrder id="campaignDateRangeValidator" components="startDate endDate" message="Start Date must be before End Date"/>
                                <p:message for="campaignDateRangeValidator"/>
                            </h:panelGroup>
                        </h:panelGrid>
                    </p:panel>
                </p:tab>
            </p:tabView>
            <p:commandButton value="Save" action="#{testBean.save}"
                             process="@form" update="@form"
                             oncomplete="if (!args.validationFailed) { PF('testDialogJS').hide(); }"/>
        </h:form>
    </p:dialog>
</h:body>

Setting the start date to, say, 10/1/2014, and the end date to 9/30/2014, then clicking the save button, the validator error message is properly displayed. However, if the commandButton's process attribute is set to @(.tab2Panel :input) @this, the validator is never called in code. I breakpointed in ValidateOrder's validateValues method - it's never called. And thus, the action is allowed to proceed.

Looking at the AJAX XHR, javax.faces.partial.execute is set to the component ID of the form in the passing case, while it's set to the explicit list of individual field component IDs to bind in the failing case (without the component ID of the form).

Is this a bug? Unsupported? etc? If unsupported, any suggestions on how to handle this desired usage? Thanks!

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Scott Balmos
  • 331
  • 4
  • 15

1 Answers1

1

The OmniFaces multi-field validators are designed as UI components, because it's among others otherwise not possible to get multi-field validation to work inside e.g. a <h:dataTable>. On contrary to standard JSF validators such as <f:validator>, which are basically taghandlers, the <o:validateOrder> component must therefore also be covered in the process attribute of <p:commandButton> (and equivalently also in execute attribute of <f:ajax>).

Your best bet is to explicitly process the entire tab instead of only the tab's input components. E.g.

<p:tabView id="tabs">
    <p:tab id="tab2">
        ...
    </p:tab>
</p:tabView>
<p:commandButton ... process="@this tabs:tab2" />
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Ah k, and since the validator is a non-PrimeFaces UI component, PF wouldn't necessarily know to include the validator component in the generated XHR's execute component list? That all makes sense. And processing the tab works. I just have to go back to the real app now to see if there was a reason why I didn't just process the tab in the first place. :) Thanks! – Scott Balmos Sep 30 '14 at 20:28
  • You're welcome. Nope, your PFS only selects inside HTML elements having `tab2Panel` class all HTML `` elements having an `id`. The `` doesn't generate anything to HTML, so there's also nothing which jQuery could select and convert to `id`s for `process`. If you actually wonder how exactly PFS work, head to this Q&A: http://stackoverflow.com/q/20080861 Instead of processing the entire tab, you can also explicitly add the `id` of `` to the `process` attribute. – BalusC Sep 30 '14 at 20:32
  • Doh. Nevermind. Yeah, I forgot that the validator doesn't generate anything client-side. I knew the end-effect and some parts in-between. Brain disconnected from fingers on the keyboard for a few moments. Thanks for the link too. – Scott Balmos Sep 30 '14 at 20:37