渲染其他forms的Ajax导致其视图状态丢失,我该如何添加回来?
我有
<h:form> <h:commandLink action="#{my_fake_ajax_link}"> <h:outputText value="Link" /> <f:ajax render=":mydiv" /> </h:commandLink> </h:form> <h:panelGroup layout="block" id="mydiv"> <h:form> <h:commandLink action="#{mybean.delete(0)}"> <h:outputText value="Here" /> <f:ajax render="@form" /> </h:commandLink> </h:form> </h:panelGroup>
当我点击一次“my_fake_ajax_link”,那么我必须点击两次“删除”链接。 这只是一个例子。 我没有这个真实的案例。 我在一个页面上有多个表单,我不能只用一个表单添加所有的表单。
我检查了问题是什么,它是:
- 当你点击“my_fake_ajax_link”时,
mydiv
像使用ajax一样刷新。 - ajax刷新表单的ViewState丢失。
我如何添加ViewState? 我怎样才能使它不工作,只使用一种forms? 这看起来像一个JSF错误给我。 我不想自动刷新该div
jQuery("#mydiv").load(document.location.href);
但我会在最糟的情况下成为可能的。
这是JSF自动包含的jsf.js
库中的一个已知问题,它处理ajax响应。 另请参阅即将发布的JSF 2.3中修复的JSF规范问题790 。 与此同时,在JSF 2.0 / 2.1 / 2.2中,您必须在render
属性中明确指定另一个<h:form>
的ID,以触发视图状态的正确添加。
<h:form> <h:commandLink action="#{my_fake_ajax_link}"> <h:outputText value="Link" /> <f:ajax render=":mydiv :mydivForm" /> </h:commandLink> </h:form> <h:panelGroup layout="block" id="mydiv"> <h:form id="mydivForm"> <h:commandLink action="#{mybean.delete(0)}"> <h:outputText value="Here" /> <f:ajax render="@form" /> </h:commandLink> </h:form> </h:panelGroup>
不,这不会导致ajax响应中的任何开销或标记重复。 或者,使用OmniFaces fixviewstate.js
。
也可以看看:
- JSF 2.0中的通信 – 包含另一个表单的内容的Ajax呈现
- h:commandButton / h:commandLink不能在第一次点击时使用,只能在第二次点击时使用
解决方法:
首先,您需要为发送ajax请求的button设置一个onevent
处理程序:
<h:form id="newComment"> <h:commandButton id="saveNewComment" action="#{postBean.actionSaveNewCommentAjax}" value="#{rb['speichern']}"> <f:ajax execute="@form" render=":commentsBox" onevent="function(data) { fixOtherFormsViewState(data, 'newComment') }" /> </h:commandButton> </h:form>
然后你需要声明这个JavaScript方法,将采取正确的viewState值,并将其添加到所有没有它的窗体:
<h:outputScript> function fixOtherFormsViewState(data, goodFormId) { if (data.status != "success") { return; } var viewState = jQuery("#" + goodFormId + " input[name='javax.faces.ViewState']").val(); jQuery("form:not(:contains(input[name='javax.faces.ViewState']))").each(function (idx, elem) { var form = jQuery(elem); var input = jQuery("<input type='hidden' name='javax.faces.ViewState' />").val(viewState); form.append(input); }); } </h:outputScript>