未处理有条件渲染组件中的表单提交
Posted
技术标签:
【中文标题】未处理有条件渲染组件中的表单提交【英文标题】:Form submit in conditionally rendered component is not processed 【发布时间】:2017-03-22 07:13:04 【问题描述】:我有一个带有表单的自定义标记文件:
<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。
【问题讨论】:
【参考方案1】:您的具体问题是由两个事实引起的:
-
当 JSF 需要解码表单提交操作或提交的输入值时,它还会检查组件是否已呈现(以防止被黑客/篡改的请求)。
在每个 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 保持在请求范围内,则在 <o:inputHidden>
中携带 rendered
属性后面的条件。调整您的 sn-p 以将其包含在 <h:form>
中。
<o:inputHidden value="#backingTest.flag" />
另见:
commandButton/commandLink/ajax action/listener method not invoked or input value not set/updated - 第 6 点 How to choose the right bean scope?【讨论】:
我也有类似的问题。是否有任何解决方法可以使用请求范围的 bean 实现解决方案?与我的情况一样,Web 应用程序已经很大,并且由于其他几个原因,bean 必须具有请求范围。以上是关于未处理有条件渲染组件中的表单提交的主要内容,如果未能解决你的问题,请参考以下文章