Answers:
每当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开发人员工具集,然后打开“ 控制台”标签),然后在下面列出可能的原因。
UICommand
并且UIInput
组件必须放置在UIForm
组件内部,例如<h:form>
(因此不是纯HTML <form>
),否则无法将任何内容发送到服务器。UICommand
组件也必须没有type="button"
属性,否则它将是一个失效按钮,仅对JavaScript有用onclick
。另请参见如何在JSF bean中发送表单输入值和调用方法,并且<h:commandButton>不会启动回发。
您不能相互嵌套多个UIForm
组件。这在HTML中是非法的。浏览器行为未指定。当心包含文件!您可以UIForm
并行使用组件,但是在提交期间它们不会相互处理。您还应该提防“上帝形态”反模式;确保您不会无意间以相同的形式处理/验证所有其他(不可见的)输入(例如,具有与输入相同形式的隐藏对话框的隐藏对话框)。另请参见如何在JSF页面中使用<h:form>?单一表格?多种形式?嵌套表格?。
没有UIInput
值验证/转换错误应该发生。您可以<h:messages>
用来显示任何特定于输入的<h:message>
组件未显示的消息。不要忘了包括id
的<h:messages>
中<f:ajax render>
,如果有的话,那么它将以及对Ajax请求被更新。另请参见当按下p:commandButton时,h:messages不显示消息。
如果UICommand
或UIInput
组件放置在诸如<h:dataTable>
,<ui:repeat>
等的迭代组件内,那么您需要确保value
在表单提交请求的应用请求值阶段中保留与迭代组件完全相同的组件。JSF将在其上重申以找到单击的链接/按钮和提交的输入值。将bean放入视图范围和/或确保将数据模型加载@PostConstruct
到bean中(因此不在getter方法中!)应该可以修复它。另请参见如何以及何时从数据库中为h:dataTable加载模型。
如果动态源(例如)包含UICommand
或UIInput
组件<ui:include src="#{bean.include}">
,那么您需要确保#{bean.include}
在表单提交请求的视图构建期间保留完全相同的值。JSF将在构建组件树期间重新执行它。将bean放入视图范围和/或确保将数据模型加载@PostConstruct
到bean中(因此不在getter方法中!)应该可以修复它。另请参阅如何通过导航菜单Ajax刷新动态包含内容?(JSF SPA)。
该rendered
组件及其所有的父母和属性test
任何父的属性<c:if>
/ <c:when>
不应计算为false
在申请表格的请求值阶段提交请求。JSF将对其进行重新检查,以作为防范被篡改/被黑客入侵的保护措施的一部分。将负责该条件的变量存储在@ViewScoped
Bean中,或者确保您正确地预先初始化@PostConstruct
了@RequestScoped
Bean 的条件,则应对其进行修复。这同样适用于disabled
组件的属性,true
在应用请求值阶段不应评估该属性。另请参见未调用JSF CommandButton操作,不处理有条件呈现的组件中的表单提交和一旦将其包装在<h:panelGroup rendering>中,h:commandButton将不起作用。
在onclick
该属性UICommand
组件和onsubmit
该属性UIForm
组件不应该返回false
或导致JavaScript错误。应该在的情况下,<h:commandLink>
或者<f:ajax>
还没有在浏览器的JS控制台可见JS错误。通常,使用Google搜索确切的错误消息已经可以给您答案。另请参见使用PrimeFaces手动添加/加载jQuery会导致Uncaught TypeErrors。
如果通过JSF 2.x <f:ajax>
或例如PrimeFaces 使用Ajax <p:commandXxx>
,请确保<h:head>
在主模板中使用而不是<head>
。否则,JSF将无法自动包含包含Ajax函数的必要JavaScript文件。这将导致浏览器的JS控制台出现JavaScript错误,例如“未定义mojarra”或“未定义PrimeFaces”。另请参见与f:ajax和ui:repeat一起使用时,不会调用h:commandLink actionlistener。
如果您使用的是Ajax,并且提交的值最终为null
,那么请确保或所关注的,UIInput
和UICommand
组件被<f:ajax execute>
或例如覆盖<p:commandXxx process>
,否则它们将不会执行/处理。另请参见将<f:ajax>添加到<h:commandButton>并了解PrimeFaces流程/更新和JSF f:ajax执行/渲染属性时,模型中未更新提交表单值。
如果提交的值仍然是null
,并且您正在使用CDI管理Bean,则请确保从正确的程序包中导入范围注释,否则CDI将默认设置为@Dependent
在EL的每次评估中有效地重新创建Bean表达。另请参见@SessionScoped bean一直释放作用域并一直重新创建,字段变为空,并且JSF 2应用程序中的默认Managed Bean Scope是什么?
如果<h:form>
带有该UICommand
按钮的的父项事先是由来自同一页面中另一表单的ajax请求呈现/更新的,则第一个操作在JSF 2.2或更早版本中将始终失败。第二步和后续操作将起作用。这是由视图状态处理中的错误引起的,该错误报告为JSF规范问题790,当前已在JSF 2.3中修复。对于老版本的JSF,你需要明确指定的标识<h:form>
中render
的<f:ajax>
。另请参见h:commandButton / h:commandLink在第一次单击时不起作用,仅在第二次单击时起作用。
如果<h:form>
已enctype="multipart/form-data"
设置为支持文件上传,则需要确保至少使用JSF 2.2,或者已正确配置了负责解析多部分/表单数据请求的servlet过滤器,否则FacesServlet
将最终根本没有获得任何请求参数,因此无法应用请求值。如何配置此类过滤器取决于所使用的文件上传组件。对于“战斧” <t:inputFileUpload>
,请检查此答案,对于PrimeFaces <p:fileUpload>
,请检查此答案。或者,如果您实际上根本没有上传文件,请完全删除该属性。
确保ActionEvent
of 的参数actionListener
是an javax.faces.event.ActionEvent
,因此不是java.awt.event.ActionEvent
,这是大多数IDE建议的第1个自动完成选项。如果使用,没有参数也是错误的actionListener="#{bean.method}"
。如果您不想在方法中使用参数,请使用actionListener="#{bean.method()}"
。或者,也许您实际上想使用action
而不是actionListener
。另请参见action和actionListener之间的区别。
确保请求-响应链中的no PhaseListener
或任何内容都不EventListener
更改JSF生命周期,以通过调用FacesContext#renderResponse()
或来跳过调用动作阶段FacesContext#responseComplete()
。
确保否Filter
或Servlet
同一请求-响应链中的请求以FacesServlet
某种方式阻止了该请求。例如,登录/安全过滤器,例如Spring Security。特别是在ajax请求中,默认情况下最终将完全没有UI反馈。另请参阅Spring Security 4和PrimeFaces 5 AJAX请求处理。
如果您使用的是PrimeFaces <p:dialog>
或a <p:overlayPanel>
,则请确保它们具有自己的<h:form>
。因为,这些组件在默认情况下被JavaScript重定位到HTML的末尾<body>
。因此,如果他们最初坐在内<form>
,则现在不再坐在内<form>
。另请参阅p:commandbutton动作在p:dialog中不起作用
框架中的错误。例如,当使用带有属性(或在某些情况下为子元素)的UI元素时,RichFaces会出现“ 转换错误 ” 。当没有为日历日期设置任何值时,此错误阻止Bean方法被调用。跟踪框架的错误可以通过从一个简单的工作示例开始并备份页面直到发现该错误来完成。rich:calendar
defaultLabel
rich:placeholder
万一您仍然卡住,该进行调试了。在客户端,按Web浏览器中的F12打开Web开发人员工具集。单击控制台选项卡,以便查看JavaScript。它应该没有任何JavaScript错误。下面的屏幕截图是来自Chrome的示例,演示了<f:ajax>
在未<h:head>
声明的情况下提交已启用按钮的情况(如上文第7点所述)。
单击网络选项卡以查看HTTP流量监视器。提交表单并调查请求标题和表单数据以及响应正文是否符合预期。下面的屏幕截图是一个来自Chrome的示例,该示例演示了一个简单表单的成功ajax提交,该表单带有一个<h:inputText>
,一个<h:commandButton>
带有<f:ajax execute="@form" render="@form">
。
(警告:当您在生产环境中从上述HTTP请求标头发布屏幕截图时,请确保对屏幕截图中的所有会话cookie进行加扰/模糊处理,以避免会话劫持攻击!)
在服务器端,请确保服务器以调试模式启动。将调试断点放在感兴趣的JSF组件的方法中,您希望在处理表单提交期间调用该方法。例如,在的情况下,UICommand
部件,这将是UICommand#queueEvent()
与在的情况下,UIInput
部件,这将是UIInput#validate()
。只需逐步执行代码并检查流程和变量是否符合预期即可。屏幕截图下方是Eclipse调试器的示例。
如果您h:commandLink
在内h:dataTable
,则还有其他原因h:commandLink
可能导致无法使用:
绑定到的底层数据源h:dataTable
也必须在单击链接时触发的第二个JSF-Lifecycle中可用。
因此,如果基础数据源是请求范围的,h:commandLink
则无法使用!
尽管我的回答并非100%适用,但是大多数搜索引擎都将其作为第一匹配,但我还是决定将其发布:
如果您使用的是PrimeFaces(或某些类似的API)p:commandButton
或p:commandLink
,则可能忘记了显式添加process="@this"
到命令组件中。
正如《 PrimeFaces用户指南》在3.18节中所述,process
和的默认值update
都是both @form
,这与您可能期望普通JSF f:ajax
或RichFaces 的默认值分别为execute="@this"
和render="@none"
相对。
只是花了我很长一段时间才能找到答案。(...而且我认为使用不同于JSF的默认值相当不明智!)
process
值为@form
。因此,如果不是以这种方式调用操作,而是在使用时调用@this
,则很可能适用我的答案的第3点。
p:commandButton
添加之前,我没有调用actionListener方法process="@this"
。此外,《 PrimeFaces用户指南》明确列出了我在3.18和3.19节中提到的默认设置。它在这里:primefaces.googlecode.com/files/primefaces_users_guide_3_4.pdf ...也许默认值已更改?
process="@this"
并添加<p:messages autoUpdate="true">
(或仅读取服务器日志以获取排队但未显示的消息),您将看到实际上发生了转换/验证错误。
我还要提到与Primefaces有关的另一件事p:commandButton
!
当您将a p:commandButton
用于需要在服务器上完成的操作时,您将无法使用,type="button"
因为那是用于按钮的按钮,这些按钮用于执行自定义javascript,而不会引起对服务器的ajax / non-ajax请求。
为此,您可以分配type
属性(默认值为"submit"
),也可以显式使用type="submit"
。
希望这会对某人有所帮助!
p:commandButton
具有type
属性的多个值,并且button
是与客户端有关的所有问题。这是一个有点难以找到这个在Primefaces
文档,但这里是一个链接:developer.am/primefaces/...
最近,我遇到了一个问题,即使用IBM Extended Faces Components的JSF 1.2应用程序中没有调用UICommand。
我在数据表的一行上有一个命令按钮(扩展版本,所以<hx:datatable>
),并且UICommand不会从表中的某些行触发(不会触发的行大于默认行显示大小的行)。
我有一个下拉组件,用于选择要显示的行数。支持该字段的值为in RequestScope
。支持表本身的数据是某种形式的ViewScope
(实际上是,临时存在SessionScope
)。
如果通过控件增加了行显示,该值也绑定到了数据表的rows
属性,则单击此命令后,由于该更改而显示的所有行都不会触发UICommand。
将此属性放在与表数据本身相同的作用域中可以解决此问题。
我认为在上面的BalusC#4中已经提到了这一点,但不仅表值需要在View或Session范围内,而且还需要控制在该表上显示的行数的属性。
我也遇到了这个问题,只有在打开浏览器的Web控制台后才真正着手解决根本问题。在此之前,我无法获得任何错误消息(即使使用也不可以<p:messages>
)。Web控制台显示了来自的HTTP 405状态代码<h:commandButton type="submit" action="#{myBean.submit}">
。
就我而言,我混合使用了普通的HttpServlet通过Auth0和JSF facelets提供OAuth身份验证,并且执行我的应用程序视图和业务逻辑的bean。
一旦我重构了web.xml,并删除了一个中间人servlet,它就“神奇地”工作了。
最重要的是,问题在于中间人servlet正在使用RequestDispatcher.forward(...)从HttpServlet环境重定向到JSF环境,而在它之前调用的servlet是通过HttpServletResponse.sendRedirect(.. )。
基本上,使用sendRedirect()允许JSF“容器”进行控制,而RequestDispatcher.forward()显然不是。
我不知道的是为什么facelet可以访问bean属性却不能设置它们,而这显然使servlet和JSF的混合消失了,但是我希望这可以帮助某人避免花费很多时间到桌子撞。
另一种可能性:如果症状是第一次调用有效,但随后的调用无效,则可能是在带有JSF 2.2的PrimeFaces 3.x上使用的,如此处所述:没有发送ViewState。
我解决了放置以下内容的问题:
<h:commandButton class="btn btn-danger" value = "Remove" action="#{deleteEmployeeBean.delete}"></h:commandButton>
在:
<h:form>
<h:commandButton class="btn btn-danger" value = "Remove" action="#{deleteEmployeeBean.delete}"></h:commandButton>
</h:form>
这是为我工作的解决方案。
<p:commandButton id="b1" value="Save" process="userGroupSetupForm"
actionListener="#{userGroupSetupController.saveData()}"
update="growl userGroupList userGroupSetupForm" />
在这里,对于Ajax调用,必须使用process =“ userGroupSetupForm”属性。actionListener正在从@ViewScope Bean调用方法。还更新咆哮消息,数据表:userGroupList和窗体:userGroupSetupForm。
<ui:composition>
<h:form id="form1">
<p:dialog id="dialog1">
<p:commandButton value="Save" action="#{bean.method1}" /> <!--Working-->
</p:dialog>
</h:form>
<h:form id="form2">
<p:dialog id="dialog2">
<p:commandButton value="Save" action="#{bean.method2}" /> <!--Not Working-->
</p:dialog>
</h:form>
</ui:composition>
解决
<ui:composition>
<h:form id="form1">
<p:dialog id="dialog1">
<p:commandButton value="Save" action="#{bean.method1}" /> <!-- Working -->
</p:dialog>
<p:dialog id="dialog2">
<p:commandButton value="Save" action="#{bean.method2}" /> <!--Working -->
</p:dialog>
</h:form>
<h:form id="form2">
<!-- .......... -->
</h:form>
</ui:composition>