selectOneButton 在 splitButton 中无法提交

selectOneButton cant submit while inside splitButton

我正在使用 JSF 2 和 primefaces 5.1,我有一个有 2 个值的 selectOneButton, EN/FR,我希望每次更改语言时都能得到通知,然后更改页面的语言环境。 现在的问题是这个 selectOneButton 在 splitButton 里面,出于某种原因, "change" 事件的 ajax 提交始终为 selectOneButton 返回 null,并且它从不传递选定的值。

<h:form prependId="false" id="headerForm">
    <p:splitButton>
        <p:menuitem>
        <p:selectOneButton id="langs" value="#{bean.lang}" >
            <f:selectItem itemLabel="English" itemValue="en"/>
            <f:selectItem itemLabel="Françcais" itemValue="fr"/>
            <f:ajax event="change"/>
        </p:selectOneButton>
        </p:menuitem>
    </p:splitButton>

这只是为了测试:

public void setLang(String lang) {
        System.out.println("Changed: " + lang);
        this.lang = lang;
}

例如,当我将 selectOneButton 放在 p:menu 中时,它工作得很好。

这个问题有两个方面。

首先,大多数 PrimeFaces 组件,尤其是那些生成隐藏 HTML 输入元素并通过一堆 divs/lists 带有点击侦听器而不是 "plain HTML" 输入呈现给最终用户的组件,需要 <p:ajax> 而不是 <f:ajax> 在 ajax 提交期间得到正确处理。

<p:selectOneButton id="lang" value="#{bean.lang}" >
    <f:selectItem itemLabel="English" itemValue="en"/>
    <f:selectItem itemLabel="Français" itemValue="fr"/>
    <p:ajax />
</p:selectOneButton>

请注意,我省略了 event 属性,因为它已经具有正确的默认值,在输入的情况下为 valueChange,在命令的情况下为 actionchange 的值不一定是正确的默认值,因为某些组件需要 click,特别是具有固定值的单选按钮和复选框。

无论如何,一般建议是,如果您使用的是 PrimeFaces,请始终坚持使用 <p:ajax>。它将使用 PrimeFaces 特定的 jQuery 基于 Ajax API 来处理 ajax 请求而不是 JSF 本机 Ajax API 并且它能够处理 PrimeFaces 组件。

其次,与 <p:splitButton> 关联的 JavaScript 代码将菜单的 HTML 表示移动到正文末尾(以确保 z-index 的最佳跨浏览器兼容性).然而,这会导致菜单不再位于表格中。您可以通过右键单击和 Inspect Element(不是 View Source 查看网络浏览器中的 HTML DOM 树来确认它]!)。您基本上可以通过两种方式解决此问题:

  1. 将表单移至菜单项内。为这个特定要求提交所有其他菜单项无论如何都没有意义。

    <p:splitButton>
        <p:menuitem>
            <h:form id="languageForm">
                <p:selectOneButton id="lang" value="#{bean.lang}" >
                    <f:selectItem itemLabel="English" itemValue="en"/>
                    <f:selectItem itemLabel="Français" itemValue="fr"/>
                    <p:ajax />
                </p:selectOneButton>
            </h:form>
        </p:menuitem>
    </p:splitButton>
    
  2. 使用<p:ajax partialSubmit="true">让PrimeFaces Ajax API收集个人输入值而不是搜索<form>serializing 它(这会失败,因为没有表格)。

    <h:form id="headerForm">
        <p:splitButton>
            <p:menuitem>
                <p:selectOneButton id="lang" value="#{bean.lang}" >
                    <f:selectItem itemLabel="English" itemValue="en"/>
                    <f:selectItem itemLabel="Français" itemValue="fr"/>
                    <p:ajax partialSubmit="true" />
                </p:selectOneButton>
            </p:menuitem>
        </p:splitButton>
    </h:form>