【问题标题】:Form submit in conditionally rendered component is not processed未处理有条件渲染组件中的表单提交
【发布时间】:2017-04-15 18:50:18
【问题描述】:

我有一个带有表单的自定义标记文件:

<h:form>
    <h:commandButton value="click">
        <f:ajax event="click" listener="#{bean[method]}" />
    </h:commandButton>
</h:form>

我通过 ajax 有条件地渲染它,如下所示:

<h:panelGroup id="test">
  <h:form>
    <h:commandButton value="click">
      <f:ajax event="click" listener="#{backingTest.updateFlag}" render=":test"/>
    </h:commandButton>
  </h:form>
  <h:panelGroup rendered="#{backingTest.flag}">
    <my:customtag bean="#{backingTest}" method="printMessage"/>
  </h:panelGroup>
</h:panelGroup>

这是关联的支持 bean:

import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;

@ManagedBean
@RequestScoped
public class BackingTest {

    private boolean flag = false;

    public void printMessage() {
        System.out.println("hello");
    }

    public void updateFlag() {
        flag = true;
    }

    public boolean getFlag() {
        return flag;
    }
}

当我单击第一个命令按钮时,updateFlag() 方法被正确调用,第二个命令按钮被正确显示。但是当我点击第二个命令按钮时,它永远不会点击printMessage() 方法。在 Web 浏览器的 JS 控制台和 HTTP 流量监视器中,我可以看到 click 事件已成功触发,并且 XHR POST 请求已成功发送。

如果我删除 rendered 属性,那么一切都会按预期工作。

这是如何引起的,我该如何解决?我正在使用 Mojarra 2.1.25。

【问题讨论】:

    标签: ajax jsf jsf-2 conditional-rendering


    【解决方案1】:

    您的具体问题是由两个事实引起的:

    1. 当 JSF 需要解码表单提交操作或提交的输入值时,它还会检查组件是否已呈现(以防止被黑客/篡改的请求)。
    2. 在每个 HTTP 请求上都会重新创建请求范围的 bean(一个 ajax 请求也算作一个请求!)。

    在您的特定情况下,rendered 条件已评估 false,而 JSF 需要解码表单提交操作,因此从不处理未呈现的输入/命令组件。

    将 bean 放在视图范围内应该可以修复它。下面的示例假设 JSF 2.x。

    import javax.faces.bean.ManagedBean;
    import javax.faces.bean.ViewScoped;
    
    @ManagedBean
    @ViewScoped
    

    下面的例子假设 JSF 2.2+ 和 CDI:

    import javax.inject.Named;
    import javax.faces.view.ViewScoped;
    
    @Named
    @ViewScoped
    

    或者,如果技术要求是将 bean 保持在请求范围内,则在 &lt;o:inputHidden&gt; 中携带 rendered 属性后面的条件。调整您的 sn-p 以将其包含在 &lt;h:form&gt; 中。

    <o:inputHidden value="#{backingTest.flag}" />
    

    另见:

    【讨论】:

    • 我也有类似的问题。是否有任何解决方法可以使用请求范围的 bean 实现解决方案?与我的情况一样,Web 应用程序已经很大,并且由于其他几个原因,bean 必须具有请求范围。
    猜你喜欢
    • 1970-01-01
    • 2015-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多