如果 UICommand 或 UIInput 组件放在迭代组件(如 <h:dataTable> , <ui:repeat> 等)内,则需要确保在表单提交请求的应用请求值阶段保留了完全相同的迭代组件 value . JSF将重申它以查找单击的链接/按钮和提交的输入值 . 将bean放在视图范围中和/或确保在bean的 @PostConstruct 中加载数据模型(因此不在getter方法中!)应该修复它 . 另见How and when should I load the model from database for h:dataTable .
10 回答
如果
h:commandLink
在h:dataTable
内,还有另一个原因导致h:commandLink
可能无效:潜在的绑定到
h:dataTable
的数据源也必须在单击链接时触发的第二个JSF生命周期中可用 .因此,如果底层数据源是请求作用域,则
h:commandLink
不起作用!简介
只要
UICommand
组件(<h:commandXxx>
,<p:commandXxx>
等)无法调用关联的操作方法,或者UIInput
组件(<h:inputXxx>
,<p:inputXxxx>
等)无法处理提交的值和/或更新模型值,并且您没有看到服务器日志中的任何googlable异常和/或警告,当你按照Exception handling in JSF ajax requests配置ajax异常处理程序时,也不会在web.xml
中设置下面的context参数时,并且您也没有在浏览器的JavaScript控制台中看到任何可搜索的错误和/或警告(按Chrome / Firefox23 / IE9中的F12打开Web开发人员工具集,然后打开控制台选项卡),然后通过以下可能原因列表进行操作 .
可能的原因
UICommand
和UIInput
组件必须放在UIForm
组件内,例如<h:form>
(因此不是普通的HTML<form>
),否则什么都不能发送到服务器 .UICommand
组件也必须没有type="button"
属性,否则它将是一个死按钮,仅对JavaScriptonclick
有用 . 另见How to send form input values and invoke a method in JSF bean和<h:commandButton> does not initiate a postback .您不能将多个
UIForm
组件相互嵌套 . 这在HTML中是非法的 . 浏览器行为未指定 . 注意包含文件!您可以并行使用UIForm
组件,但是它们无意中以相同的形式处理/验证所有其他(不可见)输入(例如,以相同的形式具有所需输入的隐藏对话框) . 另见How to use <h:form> in JSF page? Single form? Multiple forms? Nested forms? .不应发生
UIInput
值验证/转换错误 . 您可以使用<h:messages>
显示任何特定于输入的<h:message>
组件未显示的消息 . 不要忘记在<f:ajax render>
中包含<h:messages>
的<h:messages>
(如果有的话),这样它也会在ajax请求中更新 . 另见h:messages does not display messages when p:commandButton is pressed .如果
UICommand
或UIInput
组件放在迭代组件(如<h:dataTable>
,<ui:repeat>
等)内,则需要确保在表单提交请求的应用请求值阶段保留了完全相同的迭代组件value
. JSF将重申它以查找单击的链接/按钮和提交的输入值 . 将bean放在视图范围中和/或确保在bean的@PostConstruct
中加载数据模型(因此不在getter方法中!)应该修复它 . 另见How and when should I load the model from database for h:dataTable .如果动态源(如
<ui:include src="#{bean.include}">
)包含UICommand
或UIInput
组件,则需要确保在表单提交请求的视图构建期间保留完全相同的#{bean.include}
值 . JSF将在构建组件树期间重新执行它 . 将bean放在视图范围中和/或确保在bean的@PostConstruct
中加载数据模型(因此不在getter方法中!)应该修复它 . 另见How to ajax-refresh dynamic include content by navigation menu? (JSF SPA) .组件及其所有父项的
rendered
属性以及任何父项<c:if>
/<c:when>
的test
属性在表单提交请求的应用请求值阶段不应评估为false
. JSF将重新检查它作为防范篡改/黑客攻击请求的一部分 . 在@ViewScoped
bean中存储负责条件的变量,或者确保在@RequestScoped
bean的@PostConstruct
中正确预先初始化该条件应该修复它 . 这同样适用于组件的disabled
属性,在应用请求值阶段不应评估为true
. 另见JSF CommandButton action not invoked和Form submit in conditionally rendered component is not processed .UICommand
组件的onclick
属性和UIForm
组件的onsubmit
属性不应返回false
或导致JavaScript错误 . 如果<h:commandLink>
或<f:ajax>
也应该在浏览器的JS控制台中看不到JS错误 . 通常谷歌搜索确切的错误信息已经给你答案 . 另见Adding jQuery to PrimeFaces results in Uncaught TypeError over all place .如果您通过JSF 2.x
<f:ajax>
或例如使用AjaxPrimeFaces<p:commandXxx>
,确保主模板中有<h:head>
而不是<head>
. 否则JSF赢得了_b97633_的JS控制台 . 另见h:commandLink actionlistener is not invoked when used with f:ajax and ui:repeat .如果您正在使用Ajax,请确保
<f:ajax execute>
涵盖感兴趣的UIInput
和UICommand
组件 .<p:commandXxx process>
,否则将无法执行/处理 . 另见Submitted form values not updated in model when adding <f:ajax> to <h:commandButton>和Understanding PrimeFaces process/update and JSF f:ajax execute/render attributes .如果具有
UICommand
按钮的<h:form>
的父级预先由来自同一页面中的另一个表单的ajax请求呈现/更新,则第一个操作将始终失败 . 第二个及后续操作将起作用 . 这是由视图状态处理中的错误引起的,该错误报告为JSF spec issue 790并且当前计划在JSF 2.3中修复 . 对于较旧的JSF版本,您需要在<f:ajax>
的render
中显式指定<h:form>
的ID . 另见h:commandButton/h:commandLink does not work on first click, works only on second click .如果
<h:form>
已设置enctype="multipart/form-data"
以支持文件上载,那么您需要确保至少使用JSF 2.2,或者正确配置负责解析multipart / form-data请求的servlet过滤器,否则FacesServlet
将最终没有得到任何请求参数,因此无法应用请求值 . 如何配置此类过滤器取决于正在使用的文件上载组件 . 对于Tomahawk<t:inputFileUpload>
,请检查this answer和PrimeFaces<p:fileUpload>
,检查this answer . 或者,如果您实际上根本没有上传文件,则完全删除该属性 .确保
actionListener
的ActionEvent
参数是javax.faces.event.ActionEvent
,因此不是java.awt.event.ActionEvent
,这是大多数IDE建议的第一个自动完成选项 . 如果使用actionListener="#{bean.method}"
,没有参数也是错误的 . 如果您不想在方法中使用参数,请使用actionListener="#{bean.method()}"
. 或者你可能真的想使用action
而不是actionListener
. 另见Differences between action and actionListener .确保请求 - 响应链中没有
PhaseListener
或任何EventListener
已更改JSF生命周期以跳过调用操作阶段,例如调用FacesContext#renderResponse()
或FacesContext#responseComplete()
.确保同一请求 - 响应链中没有
Filter
或Servlet
以某种方式阻止了FacesServlet
的请求 .框架中的错误 . 例如,当使用
rich:calendar
UI元素和defaultLabel
属性(或者在某些情况下,rich:placeholder
子元素)时,RichFaces具有“conversion error” . 如果没有为日历日期设置任何值,则此错误会阻止调用bean方法 . 跟踪框架错误可以通过从一个简单的工作示例开始并重新构建页面直到发现错误来完成 .如果您使用的是PrimeFaces
p:dialog
或p:overlayPanel
,请确保您没有遇到p:commandbutton action doesn't work inside p:dialog调试提示
如果你仍然卡住,是时候调试了 . 在客户端,在webbrowser中按F12打开Web开发人员工具集 . 单击Console选项卡,以查看JavaScript conosle . 它应该没有任何JavaScript错误 . 下面的屏幕截图是Chrome中的一个示例,它演示了在未声明
<h:head>
时提交<f:ajax>
启用按钮的情况(如上面第7点所述) .单击“网络”选项卡以查看HTTP流量监视器 . 提交表单并调查请求 Headers 和表单数据以及响应正文是否符合预期 . 下面的屏幕截图是来自Chrome的一个示例,该示例演示了一个简单表单的成功ajax提交,其中包含单个
<h:inputText>
和单个<h:commandButton>
,其中包含<f:ajax execute="@form" render="@form">
.(警告:当您从 生产环境 环境中发布上述HTTP请求标头的屏幕截图时,请确保在屏幕截图中对任何会话cookie进行加扰/混淆,以避免会话劫持攻击!)
在服务器端,确保服务器以调试模式启动 . 将调试断点放在您期望在处理表单提交期间调用的感兴趣的JSF组件的方法中 . 例如 . 在
UICommand
组件的情况下,那将是UICommand#queueEvent(),如果是UIInput
组件,那将是UIInput#validate() . 只需逐步执行代码并检查流和变量是否符合预期 . 下面的截图是Eclipse调试器的一个例子 .虽然我的答案不是100%适用,但大多数搜索引擎都认为这是第一次点击,我决定发布它:
如果您正在使用 PrimeFaces (或某些类似的API)
p:commandButton
或p:commandLink
,则可能忘记将process="@this"
显式添加到命令组件中 .正如PrimeFaces用户指南在3.18节中所述,
process
和update
的默认值都是@form
,这几乎与您可能期望的普通JSFf:ajax
或RichFaces(分别为execute="@this"
和render="@none"
)的默认值相反 .我花了很长时间才找到答案 . (...我认为使用与JSF不同的默认值是相当不清楚的!)
我会提到另一件涉及Primefaces的
p:commandButton
!当您使用
p:commandButton
进行需要在服务器上执行的操作时,您不能使用type="button"
因为 Push buttons 用于执行自定义javascript而不会向服务器发出ajax / non-ajax请求 .为此,您可以分配
type
属性(默认值为"submit"
),也可以显式使用type="submit"
.希望这会对某人有所帮助!
我自己也遇到了这个问题,并找到了解决这个问题的另一个原因 . 如果您的支持bean中没有用于* .xhtml中使用的属性的setter方法,则不会调用该操作 .
我最近遇到了一个问题,UICommand没有在使用IBM Extended Faces Components的JSF 1.2应用程序中调用 .
我在一行数据表(扩展版本,因此
<hx:datatable>
)上有一个命令按钮,并且UICommand不会从表中的某些行触发(不会触发的行是大于默认行显示大小的行) .我有一个下拉组件,用于选择要显示的行数 . 支持此字段的值在
RequestScope
中 . 支持表本身的数据是某种ViewScope
(实际上,暂时在SessionScope
中) .如果行显示通过控件增加,该值也绑定到数据表的
rows
属性,则由于此更改而显示的任何行都不会在单击时触发UICommand .将此属性放在与表数据本身相同的范围内可以解决问题 .
我认为在上面的BalusC#4中提到了这一点,但不仅表值需要是View或Session scoped,而且还有控制该表上显示的行数的属性 .
我也遇到了这个问题,并且在打开浏览器的Web控制台后才真正开始磨练根本原因 . 在此之前,我无法收到任何错误消息(即使使用
<p:messages>
) . Web控制台显示从<h:commandButton type="submit" action="#{myBean.submit}">
返回的HTTP 405状态代码 .在我的例子中,我有一个混合的vanilla HttpServlet通过Auth0和JSF facelets提供OAuth身份验证,并执行我的应用程序视图和业务逻辑 .
一旦我重构了我的web.xml,并删除了一个中间人servlet,它就“神奇地”工作了 .
最重要的是,问题是中间人servlet正在使用RequestDispatcher.forward(...)从HttpServlet环境重定向到JSF环境,而在它之前调用的servlet是用HttpServletResponse.sendRedirect重定向的(... ) .
基本上,使用sendRedirect()允许JSF“容器”控制,而RequestDispatcher.forward()显然不是 .
我不知道的是为什么facelet能够访问bean属性但无法设置它们,这显然是为了废除servlet和JSF的混合而尖叫,但我希望这有助于某人避免长时间的头 - 到餐桌拆裂 .
我有很多乐趣调试
richfaces
datatable
中的<h:commandLink>
行动拒绝解雇的问题 . 该表曾经在某个时刻工作,但没有明显原因停止 . 我不遗余力,只是发现我的rich:datatable
使用了错误的rowKeyConverter
,它返回了富有的脸,幸运地用作行键的空值 . 这阻止了我的<h:commandLink>
动作被调用 .还有一种可能性:如果症状是第一次调用有效,但后续调用没有,则可能正在使用PrimeFaces 3.x使用JSF 2.2,详见此处:No ViewState is sent .
我修正了我的问题:
在: