JSF 和 PrimeFaces 的互斥输入字段

Mutually exclusive input fields with JSF and PrimeFaces

我有一个 PrimeFaces 应用程序,我想在其中使两个输入文本字段相互排斥:用户应填写其中一个字段,但不能同时填写两个字段。

在以下示例中,用户可以通过 phone 号码或电子邮件搜索联系人。

<h:form>
    <h:outputLabel>Phone Number:
        <h:inputText id="phoneInput" value="#{contactSearch.phone}"
                     disabled="#{not empty contactSearch.email}">
            <p:ajax event="keyup" update="emailInput"/>
        </h:inputText>
    </h:outputLabel>
    <h:outputLabel>Email Address:
        <h:inputText id="emailInput" value="#{contactSearch.email}"
                     disabled="#{not empty contactSearch.phone}">
            <p:ajax event="keyup" update="phoneInput"/>
        </h:inputText>
    </h:outputLabel>

    <!-- Possibly other fields... -->

    <h:commandButton value="Search" action="#{contactSearch.search}"/>
</h:form>

这是正确的做法吗?我关心的是:

这在标准 JSF 中并非微不足道。 JSF 实用程序库 OmniFaces has a validator for exactly this purpose, the <o:validateOne>.

<h:inputText id="email" ... />
<h:inputText id="phone" ... />
<o:validateOne components="email phone" />

但是,从 UX 的角度来看,您最好重新设计表单,为 select 类型提供一个 UISelectOne 组件,并为 UIInput 提供一个字段输入值。例如

<h:selectOneRadio ... value="#{bean.type}">
    <f:selectItem itemValue="email" />
    <f:selectItem itemValue="phone" />
</h:selectOneRadio>
<h:inputText ... value="#{bean.value}" />

更新:由于服务器端验证负担不起,而且您真的很想在不产生太多 ajax 流量的情况下禁用另一个,您唯一的选择是使用纯 JavaScript/jQuery 用于作业(如有必要,结合服务器端验证作为后备)。

这是一个基于 jQuery 的通用方法:

<h:inputText styleClass="onlyone" a:data-onlyone="groupName" />
<h:inputText styleClass="onlyone" a:data-onlyone="groupName" />
...

$(document).on("input", ":input.onlyone", function() {
    var $this = $(this);
    var $others = $("[data-onlyone='" + $this.data("onlyone") + "']").not($this);
    $others.val(null).attr("disabled", !!$this.val());
});

data-onlyone 值应表示组名称,因此您可以在整个文档中输入多个 "only one"。