Scott Balmos
Scott Balmos

Reputation: 331

o:validateOrder not applied when using PFS in process attribute

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!

Upvotes: 1

Views: 163

Answers (1)

BalusC
BalusC

Reputation: 1109222

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

Upvotes: 1

Related Questions