省略 p:selectOneMenu、Ajax 请求的验证

Omit validation for p:selectOneMenu, for Ajax requests

我有一个 Jsf 页面,其中有一个片段 <p:selectOneMenu/> (主要面孔)和一个 Ajax 与之相关联。它具有默认的 select 项目“--- Select 一个 ---”和其他动态创建的项目。

此字段是必填项,因此如果用户在没有 select 的情况下提交表单,页面会显示错误消息。

当我 select 其他选项之一并再次返回 selecting“--- Select 一个 ---”时,问题就出现了。然后页面显示必填字段消息,甚至在我提交表单之前。我在 <p:ajax><p:selectOneMenu> 标签中尝试了 immediate 的不同方式,但其中 none 具有预期的行为。

<p:messages>声明如下:

-- list.xhtml

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

片段:

-- 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()));
}

这是预期的行为。将 p:ajax 标记添加到 p:selectOneMenu 时,您会在每次用户更改输入时处理该值,因此如果您将其标记为 required,它将被验证并被拒绝。对于这种情况,我最喜欢的解决方法是在按钮中包含一个请求参数以提交整个表单并在 required 属性中检查它。就是这样:

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

另请参阅:

说明

发生这种情况是因为您有一个 p:messages 组件 autoUpdate 设置为 true 并且您已将 p:ajax 附加到您的 selectOneMenu 所以任何时候您的值发生变化, p:messages 是更新。因此,由于使用 required="true",一旦您选择了“--- Select 一个 ---”,就会显示一条错误消息。

解决方案

  • ignoreAutoUpdate="true" 添加到您的 p:ajax
  • 如果不需要,请删除 autoUpdate="true"