alexpfx
alexpfx

Reputation: 6680

Omit validation for p:selectOneMenu, for Ajax requests

I have a Jsf page with a fragment with <p:selectOneMenu/> (Prime faces) and an Ajax associated with it. It have the default select item "--- Select One ---" and others items that were created dynamically.

This field is required, so if users submit the form without select, the page show a error message.

The problem occurs when I select one of this others options and go back selecting "--- Select One ---" again. Then the page shows the required field message, even before I submit the form. I try different ways of immediate in <p:ajax> and <p:selectOneMenu> tags but none of them has the expected behavior.

The <p:messages> is declared as below:

-- list.xhtml

<p:messages id="messages" autoUpdate="true" closable="true"  escape="false" />
<.... include fragment.xhtml ....>

And the fragment:

-- fragment.xhtml

<p:selectOneMenu id="selectTipoCarro"
                 value="#{carroBean.carro.tipoCarroEnum}"
                 required="true">
    <f:selectItems value="#{carroBean.listaSelectItemTipoCarroInclusao}" />
    <p:ajax update="outputInicioVigenciaWrapper outputLabelCalendarInicioVigenciaWrapper"
            listener="#{carroBean.aoMudarTipoCarro}" />
</p:selectOneMenu>

<h:panelGroup id="outputLabelCalendarInicioVigenciaWrapper">
    <h:outputLabel id="outputLabelCalendarInicioVigencia"
                   rendered="#{carroBean.edicaoDataInicioVigenciaDisponivel}"
                   for="calendarInicioVigencia">
        <span>*
            #{labels['carro.inicio.vigencia']}: </span>
        <p:calendar id="calendarInicioVigencia"
                    value="#{carroBean.carro.dataInicioVigencia}"
                    showOn="button"
                    pattern="dd/MM/yyyy" mask="true"
                    required="true"/>
    </h:outputLabel>
</h:panelGroup>

<h:panelGroup id="outputInicioVigenciaWrapper">
    <h:outputLabel for="outputInicioVigencia"
                   rendered="#{not carroBean.edicaoDataInicioVigenciaDisponivel}">
        <span aria-live="polite">
            <h:outputText id="outputInicioVigencia"
                          value="#{carroBean.carro.dataInicioVigencia}"
                          styleClass="dataFormat"
        </h:outputText>
    </span>
</h:outputLabel>
</h:panelGroup>
private SelectItem obterSelectItemSelecione() {
    SelectItem selectItem = new SelectItem("", "-- Select One --");
    return selectItem;
}

private void preencherListaSelectItemTipoCarro(List<SelectItem> select, TipoCarroEnum[] tiposCarrosConsiderados) {
    select.clear();
    select.add(obterSelectItemSelecione());
    for (TipoCarroEnum tipoCarro : tiposCarrosConsiderados) {
        select.add(new SelectItem(tipoCarro, tipoCarro.getNome()));
    }
}

public void aoMudarTipoCarro() {
    getCarro().setDataInicioVigencia(carroService.obterProximaDataInicioVigenciaDisponivel(getCarro().getTipoCarroEnum()));
}

Upvotes: 3

Views: 3286

Answers (2)

Aritz
Aritz

Reputation: 31651

That's the expected behaviour. When adding a p:ajax tag to your p:selectOneMenu you make the value be processed everytime the user changes the input, so it will be validated and rejected if you mark it as required. My favourite workaround for this cases is to include a request param in the button to submit the whole form and check for it in the required attribute. That's it:

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://xmlns.jcp.org/jsf/html"
    xmlns:f="http://xmlns.jcp.org/jsf/core"
    xmlns:p="http://primefaces.org/ui"
    xmlns:comp="http://java.sun.com/jsf/composite/comp"
    xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head />
<h:body>
    <h:form>
        <p:messages autoUpdate="true" />
        <p:selectOneMenu value="#{val}"
            required="#{param['validate']}">
            <p:ajax event="change" />
            <f:selectItem itemLabel="None" noSelectionOption="true" />
            <f:selectItem itemLabel="val1" itemValue="val1" />
        </p:selectOneMenu>
        <p:commandButton value="Submit" ajax="false">
            <f:param name="validate" value="true" />
        </p:commandButton>
    </h:form>
</h:body>
</html>

See also:

Upvotes: 4

Mathieu Castets
Mathieu Castets

Reputation: 6040

Explanation

This happens because you have a p:messages component with autoUpdate set to true and you have attached p:ajax to your selectOneMenu so anytime your value changes, p:messages is updated. Therefore, due to the use of required="true" an error messages is shown as soon as you have selected "--- Select One ---".

Solution

  • Add ignoreAutoUpdate="true" to your p:ajax or
  • Remove autoUpdate="true" if not necessary

Upvotes: 2

Related Questions