Primefaces嵌套Dialog确认按钮后端方法未调用问题
问题分析与解决方案
首先得指出你代码里的一个核心问题:你把确认弹窗(dlgConfirmar)嵌套在了Save按钮(btConfirmar)的标签内部,这完全不符合JSF组件树的规范,直接导致了确认按钮的后端绑定无法正常触发——组件结构混乱后,JSF根本没法正确识别并调用你的Bean方法,不过客户端的oncomplete是纯JS逻辑,不受组件结构影响,所以弹窗能正常关闭。
下面是一步步的修复方案:
1. 修正组件结构,把确认弹窗移出按钮标签
把dlgConfirmar弹窗从<p:commandButton>里面抽出来,放到页面的<h:form>根级别下,和第一个编辑弹窗(dlgEditar)同级。调整后的代码大概是这样:
<h:form id="form"> <!-- 你的DataTable和其他页面组件 --> <!-- 编辑设备类型的弹窗 --> <p:dialog header="Editar IP Cadastrado" id="dialog" styleClass="borderless" widgetVar="dlgEditar" modal="true" showEffect="fade" hideEffect="fade" resizable="false" draggable="false" closable="false"> <p:growl id="growlInformacao" sticky="true" /> <p:panelGrid columns="2" rendered="#{not empty cadastrosIPsBean.selectedCadastro}" style="font-size: 14px"> <p:outputLabel value="Equipamento:"/> <p:selectOneMenu id="selecionadorEquipamento" value="#{cadastrosIPsBean.selectedCadastro.equipamento}" style="width: 92%"> <f:selectItems value="#{cadastrosIPsBean.listaEquipamentosFormatada}"/> </p:selectOneMenu> </p:panelGrid> <f:facet name="footer"> <p:commandButton value="Save" id="btConfirmar" oncomplete="PF('dlgConfirmar').show()" update=":form:tbl" style="width: 125px" /> </f:facet> </p:dialog> <!-- 确认修改的弹窗,移到form根级别 --> <p:dialog appendTo="@(body)" header="Confirmar alterações" id="confirmar" widgetVar="dlgConfirmar" modal="true" showEffect="fade" hideEffect="fade" resizable="false" draggable="false"> <br/> <p:outputLabel value="Tem certeza de que deseja salvar as alterações?" style="font-size:14px"/> <br/><br/> <p:commandButton id="confirmarSim" value="Sim" action="#{cadastrosIPsBean.salvarAlteracoes}" oncomplete="PF('dlgEditar').hide(); PF('dlgConfirmar').hide();" update=":form:growlInformacao :form:tbl" style="width:80px"/> <p:commandButton value="Não" onclick="PF('dlgConfirmar').hide();" style="width:80px"/> </p:dialog> </h:form>
2. 处理appendTo="@(body)"带来的表单问题
因为你给确认弹窗加了appendTo="@(body)",这会把弹窗移到页面的body标签下,脱离了原来的<h:form>范围。这种情况下,必须在弹窗内部嵌套一个<h:form>,确保按钮能正确提交请求:
<p:dialog appendTo="@(body)" header="Confirmar alterações" id="confirmar" widgetVar="dlgConfirmar" modal="true" showEffect="fade" hideEffect="fade" resizable="false" draggable="false"> <h:form> <!-- 弹窗内部新增form --> <br/> <p:outputLabel value="Tem certeza de que deseja salvar as alterações?" style="font-size:14px"/> <br/><br/> <p:commandButton id="confirmarSim" value="Sim" action="#{cadastrosIPsBean.salvarAlteracoes}" oncomplete="PF('dlgEditar').hide(); PF('dlgConfirmar').hide();" update=":form:growlInformacao :form:tbl" style="width:80px"/> <p:commandButton value="Não" onclick="PF('dlgConfirmar').hide();" style="width:80px"/> </h:form> </p:dialog>
3. 验证后端Bean方法的正确性
最后检查一下你的cadastrosIPsBean.salvarAlteracoes方法:
- 方法必须是public的,返回值可以是
void或者用于导航的String - 确保Bean的作用域是合适的(比如
@ViewScoped,避免请求结束后Bean被销毁) - 方法参数要符合JSF action方法的规范(无参数,或者接收
ActionEvent类型的参数)
为什么原来的oncomplete能正常执行?
因为oncomplete是客户端的JavaScript逻辑,只要按钮被点击,不管服务器端的请求有没有触发,客户端的JS都会执行,所以你能看到弹窗关闭,但后端方法因为组件结构错误根本没被调用。
内容的提问来源于stack exchange,提问作者Bruno A
相关产品推荐
相关产品推荐

