I have in my JSF 2.2 + PrimeFaces application a wizard with three tabs. In each tab, I have a form to capture data from the user. Each of this form have some validations. Right now, when I click on next to go to the next tab, it is validating the data from the form. I don't want this to happen.
The user is persisting data in the data in one tab and then they want to keep moving forward. There is NO requirement to have data on the form to move to the next tab.
I was able to fix this by NOT having client side validation (i.e: not using the required word on the input fields) and validating on the backend only. The problem is I want the client side validation.
My wizard looks like this:
<h:form id="wizard">
<p:wizard flowListener="#{afiliadoController.onFlowProcess}" nextLabel="Siguiente"
backLabel="Anterior" showStepStatus="true">
<p:tab id="afiliadoTab" title="Afiliado">
<p:growl autoUpdate="true"/>
<p:panel styleClass="panels" id="panelAfiliado" style="margin-bottom:1em;" >
<p:focus context="panelAfiliado"/>
<h1> Agregue un Afiliado </h1>
<h:panelGrid columns="4" styleClass="panelGrid" >
<p:outputLabel for="nombres" value="Nombres:" />
<p:inputText id="nombres" value="#{afiliadoController.afiliado.nombre}"
requiredMessage="Debe insertar un nombre." />
<p:outputLabel for="apellidos" value="Apellidos:" />
<p:inputText id="apellidos" value="#{afiliadoController.afiliado.apellido}"
requiredMessage="Debe insertar un apellido." />
<p:outputLabel for="estadoCivil" value="Estado Civil:" />
<p:selectOneMenu id="estadoCivil" effect="drop" value="#{afiliadoController.afiliado.estado_civil}"
requiredMessage="Debe seleccionar un estado civil." >
<f:selectItem itemLabel="Estado Civil" itemValue=""/>
<f:selectItem itemLabel="Soltero" itemValue="S"/>
<f:selectItem itemLabel="Casado" itemValue="C"/>
<f:selectItem itemLabel="Union Libre" itemValue="U"/>
<f:selectItem itemLabel="Divorciado" itemValue="D"/>
<f:selectItem itemLabel="Viudo" itemValue="V"/>
</p:selectOneMenu>
<p:outputLabel for="direccion" value="Direccion:" />
<p:inputText id="direccion" value="#{afiliadoController.afiliado.direccion}"/>
<p:outputLabel for="telefono" value="Telefono:" />
<p:inputMask id="telefono" value="#{afiliadoController.afiliado.telefono}" mask="(999) 999-9999"
requiredMessage="Debe insertar un telefono." />
<p:outputLabel for="fechaNacimiento" value="Fecha de Nacimiento:"/>
<p:calendar id="fechaNacimiento" yearRange="c-100:c" pattern="dd/MM/yyyy" navigator="true"
value="#{afiliadoController.afiliado.fecha_nacimiento}"
requiredMessage="Debe insertar su fecha de nacimiento." showOn="button"
readonly="#{facesContext.currentPhaseId.ordinal eq 6}">
<p:ajax event="dateSelect" listener="#{afiliadoController.dateSelect}" update="edadAfi"/>
</p:calendar>
<p:outputLabel for="plan" value="Plan:" />
<p:selectOneMenu id="plan" effect="drop" value="#{afiliadoController.afiliado.plan}"
requiredMessage="Debe seleccionar un plan." >
<f:selectItem itemLabel="Seleccione un plan" itemValue=""/>
<f:selectItem itemLabel="Vital Base" itemValue="1"/>
<f:selectItem itemLabel="Vital Elite" itemValue="2"/>
<f:selectItem itemLabel="Plan Vital Elite Internacional" itemValue="3"/>
</p:selectOneMenu>
<h:outputText value="Fecha: #{of:formatDate(now, 'dd/MM/yyyy')}"/>
<h:outputText value="Edad Afiliado: #{afiliadoController.afiliado.edad}" id="edadAfi"/>
<p:outputLabel for="modalidad" value="Modalidad:" />
<p:selectOneMenu id="modalidad" effect="drop" value="#{afiliadoController.afiliado.modalidad}"
requiredMessage="Debe seleccionar una modalidad." required="true">
<f:selectItem itemLabel="Seleccione una modalidad" itemValue=""/>
<f:selectItem itemLabel="Solo Titular Del Contrato" itemValue="A"/>
<f:selectItem itemLabel="Titular del Contrato + Grupo Familiar" itemValue="B"/>
<f:validateBean disabled="#{!request.getParameter('validate')}" />
</p:selectOneMenu>
<p:commandButton value="Insertar" icon="fa fa-save" process="panelAfiliado" update="afiliadoTable"
actionListener="#{afiliadoController.insertAfiliado}" >
<f:param name="validate" value="true"/>
</p:commandButton>
</h:panelGrid>
</p:panel>
</p:tab>
</p:wizard>
</h:form>
It is on purpose I am displaying only the first tab to make it more readable. On this first tab I have two <h:form>
inside the main <h:form>
(I am not sure if this is good practice.)
I am doing this because I want the enter keyword to work separately on each form. The <h:form>
with id afiliadoTab has some validations. I want these validations to happen only when I click on the button:
<p:commandButton value="Insertar" icon="fa fa-save" process="panelAfiliado" update=":wizard:tablaAfiliados:afiliadoTable"
actionListener="#{afiliadoController.insertAfiliado}" validateClient="true"/>
I don't want these validations to happen when I click on NEXT. What can I do? (I know there are a few similar questions out there in SO but I couldn't quite get the answer. For example, the one below is using custom widget vars. I tried doing that but I found a few issues:
How can I display the back button only when needed? (Not display it on the first tab)
The validations are still in place, even when I use @this.
What are my best options?