未调用commandButton / commandLink / ajax操作/侦听器方法或未设置/更新输入值

你。 提交于 2020-03-07 20:03:00

有时,当使用<h:commandLink><h:commandButton><f:ajax> ,与标签关联的actionactionListenerlistener方法根本不会被调用。 或者,不使用提交的UIInput值更新Bean属性。

有哪些可能的原因和解决方案?


#1楼

尽管我的回答并非100%适用,但是大多数搜索引擎都将其作为第一匹配,但我还是决定将其发布:

如果您使用的是PrimeFaces (或类似的API) p:commandButtonp:commandLink ,则可能忘记了将process="@this"显式添加到命令组件中。

如《 PrimeFaces用户指南》第3.18节所述, processupdate的默认值均为@form ,这与您可能从纯JSF f:ajax或RichFaces中获得的默认值完全相反,它们是execute="@this"render="@none"分别为render="@none"

只是花了我很长一段时间才能找到答案。 (...而且我认为使用不同于JSF的默认值相当不明智!)


#2楼

我自己陷入了这个问题,并找到了导致该问题的另一个原因。 如果在后备bean中没有用于* .xhtml中使用的属性的setter方法,那么就不会调用该操作。


#3楼

介绍

每当UICommand组件( <h:commandXxx><p:commandXxx>等)无法调用关联的操作方法,或者UIInput组件( <h:inputXxx><p:inputXxxx>等)无法处理提交值和/或更新模型值,并且在服务器日志中看不到任何可谷歌搜索的异常和/或警告,同样,按照JSF ajax请求中的异常处理配置ajax异常处理程序时,也没有设置在web.xml中的上下文参数下面,

<context-param>
    <param-name>javax.faces.PROJECT_STAGE</param-name>
    <param-value>Development</param-value>
</context-param>

并且您也没有在浏览器的JavaScript控制台中看到任何可谷歌搜索的错误和/或警告(按Chrome / Firefox23 + / IE9 +中的F12打开Web开发人员工具集,然后打开“ 控制台”选项卡),然后在可能的原因列表下进行工作。

可能的原因

  1. UICommandUIInput组件必须放置在UIForm组件内,例如<h:form> (因此不是普通的HTML <form> ),否则什么也不能发送到服务器。 UICommand组件也不能具有type="button"属性,否则它将是一个无效按钮,仅对JavaScript onclick有用。 另请参见如何在JSF bean中发送表单输入值和调用方法,并且<h:commandButton>不会启动回发

  2. 您不能相互嵌套多个UIForm组件。 这在HTML中是非法的。 浏览器行为未指定。 当心包含文件! 您可以并行使用UIForm组件,但是在提交期间它们不会相互处理。 您还应该提防“上帝形态”反模式; 确保您不会无意间以相同的形式处理/验证所有其他(不可见的)输入(例如,具有与输入相同形式的隐藏对话框的隐藏对话框)。 另请参见如何在JSF页面中使用<h:form>? 单一表格? 多种形式? 嵌套表格?

  3. 没有应该发生UIInput值验证/转换错误。 您可以使用<h:messages>显示任何输入特定的<h:message>组件未显示的<h:message> 。 不要忘记在<f:ajax render>包含<h:messages>id (如果有的话),以便在ajax请求中也将对其进行更新。 另请参见当按下p:commandButton时,h:messages不显示消息

  4. 如果UICommandUIInput元件放置等的迭代组件内<h:dataTable><ui:repeat>等,则需要确保完全相同的value的迭代成分的过程中应用的请求的值相被保存表单提交请求。 JSF将在其上重申以找到单击的链接/按钮和提交的输入值。 将bean放在视图范围内和/或确保将数据模型加载到bean的@PostConstruct中(因此不在getter方法中!)应该可以修复它。 另请参见如何以及何时从数据库中为h:dataTable加载模型

  5. 如果动态源(如<ui:include src="#{bean.include}">包含UICommandUIInput组件,则需要确保在视图期间保留完全相同的#{bean.include}值。表单提交请求的构建时间。 JSF将在构建组件树期间重新执行它。 将bean放在视图范围内和/或确保将数据模型加载到bean的@PostConstruct中(因此不在getter方法中!)应该可以修复它。 另请参阅如何通过导航菜单Ajax刷新动态包含内容? (JSF SPA)

  6. 在表单提交请求的应用请求值阶段,组件及其所有父项的rendered属性以及任何父项<c:if> / <c:when>test属性不应评估为false 。 JSF将对其进行重新检查,以作为防范被篡改/被黑客入侵的保护措施的一部分。 将负责该条件的变量存储在@ViewScoped Bean中,或者确保您在@RequestScoped Bean的@PostConstruct中正确地@ViewScoped初始化了该条件,可以对其进行修复。 这同样适用于组件的disabled属性,在应用请求值阶段,该属性不应评估为true 。 另请参见未调用JSF CommandButton操作,并且不处理有条件呈现的组件中的Form Submit

  7. onclick的属性UICommand组件和onsubmit的属性UIForm组件不应该返回false或导致JavaScript错误。 如果<h:commandLink><f:ajax>也应该在浏览器的JS控制台中没有可见的JS错误。 通常,使用Google搜索确切的错误消息已经可以给您答案。 另请参见将jQuery添加到PrimeFaces会导致Uncaught TypeErrors

  8. 如果您通过JSF 2.x <f:ajax>或例如PrimeFaces <p:commandXxx>使用Ajax,请确保主模板中有<h:head>而不是<head> 。 否则,JSF将无法自动包含包含Ajax函数的必要JavaScript文件。 这将导致浏览器的JS控制台出现JavaScript错误,例如“未定义mojarra”或“未定义PrimeFaces”。 另请参见与f:ajax和ui:repeat一起使用时,不会调用h:commandLink actionlistener

  9. 如果您使用的是Ajax,并且提交的值最终为null ,那么请确保感兴趣的UIInputUICommand组件被<f:ajax execute>或例如<p:commandXxx process>覆盖,否则它们将不会被'将被执行/处理。 另请参见在将<f:ajax>添加到<h:commandButton>了解PrimeFaces流程/更新和JSF f:ajax执行/渲染属性 时,模型中未更新提交表单值

  10. 如果提交的值仍然最终为null ,并且您正在使用CDI管理Bean,请确保从正确的包中导入范围注释,否则CDI将默认为@Dependent ,这样可以在每次评估时有效地重新创建Bean。 EL表达式 另请参见@SessionScoped bean一直释放作用域并一直重新创建,字段变为空,并且JSF 2应用程序中的默认Managed Bean Scope是什么?

  11. 如果具有UICommand按钮的<h:form>UICommand是事先由来自同一页面中另一种表单的ajax请求呈现/更新的,则第一个操作在JSF 2.2或更早版本中将始终失败。 第二步和后续操作将起作用。 这是由视图状态处理中的错误引起的,该错误报告为JSF规范问题790 ,当前已在JSF 2.3中修复。 对于较旧的JSF版本,您需要在<f:ajax>render中显式指定<h:form>的ID。 另请参见h:commandButton / h:commandLink在第一次单击时不起作用,仅在第二次单击时起作用

  12. 如果<h:form>设置了enctype="multipart/form-data"以支持文件上传,那么您需要确保至少使用JSF 2.2,或者要确保负责该工作的servlet过滤器解析multipart / form-data请求的配置正确,否则FacesServlet最终将根本没有任何请求参数,从而无法应用请求值。 如何配置此类过滤器取决于所使用的文件上传组件。 对于“战斧” <t:inputFileUpload> ,请检查此答案 ;对于PrimeFaces <p:fileUpload> ,请检查此答案 。 或者,如果您实际上根本没有上传文件,请完全删除该属性。

  13. 确保actionListenerActionEvent参数是javax.faces.event.ActionEvent ,因此不是java.awt.event.ActionEvent ,这是大多数IDE建议的第一种自动完成选项。 如果使用actionListener="#{bean.method}"则没有参数也是错误的。 如果您不想在方法中使用参数,请使用actionListener="#{bean.method()}" 。 或者,也许您实际上是想使用action而不是actionListener 。 另请参见action和actionListener之间的区别

  14. 确保例如通过调用FacesContext#renderResponse()FacesContext#responseComplete() ,请求-响应链中的PhaseListener或任何EventListener没有更改JSF生命周期以跳过调用操作阶段。

  15. 确保同一请求-响应链中没有FilterServlet以某种方式阻止了FacesServlet的请求。

  16. 如果您使用的是PrimeFaces <p:dialog><p:overlayPanel> ,请确保它们具有自己的<h:form> 。 因为,默认情况下,JavaScript将这些组件重定位到HTML <body>末尾。 因此,如果他们最初坐在<form> ,那么现在他们将不再坐在<form> 。 另请参阅p:commandbutton动作在p:dialog中不起作用

  17. 框架中的错误。 例如,当使用带有defaultLabel属性的rich:calendar UI元素(或在某些情况下,是rich:placeholder子元素)时,RichFaces会出现“ 转换错误 ”。 当没有为日历日期设置任何值时,此错误阻止Bean方法被调用。 跟踪框架的错误可以通过从一个简单的工作示例开始并备份页面直到发现该错误来完成。

调试提示

万一您仍然卡住,该进行调试了。 在客户端,按Web浏览器中的F12打开Web开发人员工具集。 单击控制台选项卡,以便查看JavaScript。 它应该没有任何JavaScript错误。 下面的屏幕快照是Chrome的示例,演示了在未声明<h:head>的情况下提交启用<f:ajax>按钮的情况(如以上第7点所述)。

单击网络选项卡以查看HTTP流量监视器。 提交表单并调查请求标题和表单数据以及响应正文是否符合预期。 下面的屏幕快照是一个来自Chrome的示例,该示例演示了一个简单表单的成功ajax提交,该表单具有一个<h:inputText>和一个<h:commandButton>以及一个<f:ajax execute="@form" render="@form">

(警告:当您在生产环境中从上述HTTP请求标头发布屏幕截图时,请确保对屏幕截图中的所有会话cookie进行加扰/模糊处理,以避免会话劫持攻击!)

在服务器端,请确保服务器以调试模式启动。 将调试断点放在感兴趣的JSF组件的方法中,您希望在处理表单提交期间调用该方法。 例如,如果使用UICommand组件, UICommand#queueEvent() ;如果使用UIInput组件, UICommand#queueEvent() UIInput#validate() 。 只需逐步执行代码并检查流程和变量是否符合预期即可。 屏幕截图下方是Eclipse调试器的示例。


#4楼

我还要提到与Primefaces的p:commandButton有关的另一件事!

当对服务器上需要执行的操作使用p:commandButton ,不能使用type="button"因为它用于用于执行自定义javascript而不会引起ajax / non-ajax请求的按钮到服务器。

为此,您可以分配type属性(默认值为"submit" ),也可以显式使用type="submit"

希望这会对某人有所帮助!


#5楼

最近,我遇到了一个问题,即使用IBM Extended Faces Components的JSF 1.2应用程序中没有调用UICommand。

我在数据表的行上有一个命令按钮(扩展版本,所以<hx:datatable> ),UICommand不会从表中的某些行触发(不会触发的行是大于默认行的行)显示屏尺寸)。

我有一个下拉组件,用于选择要显示的行数。 支持该字段的值在RequestScope 。 支持表本身的数据在某种ViewScope (实际上,临时在SessionScope )。

如果通过控件增加了行显示,该值也绑定到了数据表的rows属性,则单击此命令后,由于此更改而显示的所有行都不会触发UICommand。

将此属性放在与表数据本身相同的作用域中可以解决此问题。

我认为在上面的BalusC#4中已经提到了这一点,但不仅表值需要在View或Session范围内,而且还需要控制在该表上显示的行数的属性。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!