Primefaces tabView executes form validation on tab

2019-04-12 12:08发布

问题:

I am having a serious issue with the p:tabView component. I have set dynamic="true" and cache="false" to the tabView. One of the tabs has some input components which are set required="true".

Now when I am changing the tab each time, the form validation is occurring and the FacesMessages are being displayed in growl.

Here is the tab:

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
   xmlns:ui="http://java.sun.com/jsf/facelets"
   xmlns:h="http://java.sun.com/jsf/html"
   xmlns:f="http://java.sun.com/jsf/core"
   xmlns:p="http://primefaces.org/ui"
   template="/WEB-INF/templates/globalTemplate.xhtml">

   <ui:define name="title">#{adbBundle['home']}</ui:define>
   <ui:define name="content">
      <p:growl id="growl" showDetail="true" autoUpdate="true" />

      <p:tabView id="adminTabView" dynamic="true" cache="false">
         <p:tab title="#{adbBundle['admin.customerTab.title']}"
            id="customerTab">
            <ui:include src="/WEB-INF/includes/adminCustomer.xhtml" />
         </p:tab>
         <p:tab title="#{adbBundle['admin.activityTab.title']}"
            id="activityTab">
            <ui:include src="/WEB-INF/includes/addActivity.xhtml" />
         </p:tab>
      </p:tabView>

   </ui:define>

</ui:composition>

The adminCustomer.xhtml contains the form and which is:

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
   xmlns:h="http://java.sun.com/jsf/html"
   xmlns:f="http://java.sun.com/jsf/core"
   xmlns:ui="http://java.sun.com/jsf/facelets"
   xmlns:p="http://primefaces.org/ui">

   <h:form id="customerForm">
      <p:panel id="addCustomerPanel" toggleable="true"
         header="#{adbBundle['admin.addCustomerPanel.header.new']}">
         <p:panelGrid columns="2" id="addCustomerTable"
            styleClass="addCustomerTable">
            <f:facet name="header">
               <p:outputLabel id="header"
                  value="#{adbBundle['admin.addCustomerPanel.addCustomerTable.header']}" />
            </f:facet>

            <p:outputLabel for="customerName"
               value="#{adbBundle['admin.addCustomerPanel.addCustomerTable.customerName']}" />
            <h:panelGroup layout="block">
               <p:inputText id="customerName" styleClass="customerName"
                  autocomplete="off"
                  label="#{adbBundle['admin.addCustomerPanel.addCustomerTable.customerName']}"
                  value="#{adminController.customerDTO.customerName}"
                  required="true" />               
            </h:panelGroup>

            <p:outputLabel for="customerId"
               value="#{adbBundle['admin.addCustomerPanel.addCustomerTable.customerId']}" />
            <h:panelGroup layout="block">
               <p:inputText id="customerId" autocomplete="off"
                  label="#{adbBundle['admin.addCustomerPanel.addCustomerTable.customerId']}"
                  value="#{adminController.customerDTO.customerId}" required="true">
                  <f:validator validatorId="customerIDValidator" />
               </p:inputText>               
            </h:panelGroup>

            <p:outputLabel for="activeStatus"
               value="#{adbBundle['admin.addCustomerPanel.addCustomerTable.activeStatus']}" />
            <h:panelGroup layout="block">
               <p:selectBooleanCheckbox id="activeStatus"
                  value="#{adminController.customerDTO.active}" />
            </h:panelGroup>

            <f:facet name="footer">
               <p:commandButton value="#{adbBundle['saveButton']}"
                  actionListener="#{adminController.saveCustomer}"
                  icon="ui-icon-check"
                  update=":growl, @form" />
            </f:facet>
         </p:panelGrid>
      </p:panel>
   </h:form>

</ui:composition>

I am unable to find what I am doing wrong and how to resolve it. I am using Primefaces 3.4.2 with JSF Mojarra 2.1.7-jbossorg. Any pointer would be very helpful to me.

I have asked this question in PrimeFaces forum too.

回答1:

This is how tabView works. Here are the relevant issues from the PrimeFaces tracker:

  • http://code.google.com/p/primefaces/issues/detail?id=3423.
  • http://code.google.com/p/primefaces/issues/detail?id=4143

As you can see the first one is marked as WontFix. The second is a duplicate but at the end you will see another workaround.

If you read that thread carefully you may notice that some workarounds still exists. Try one of them if you are forced to use tabView. Also consider using PrimeFaces - Wizard if you want to use inputs in different tabs.



回答2:

If I understand your problem correctly, there is actually a quite simple workaround to prevent the duplicate showing of messages.

Change your growl to the following:

<p:growl id="growl" globalOnly="true" autoUpdate="true" showDetail="true" />

In case you want to add messages from backing bean side you can do that with the following code:

FacesContext.getCurrentInstance()
   .addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "title", "details");

And if you want to be completely safe, you can even specify a for-attribute to the growl, and take that as the first parameter to addMessage.