通过ajax渲染其他形式会导致其视图状态丢失,如何将其添加回来?

时间:2011-10-18 12:39:18

标签: ajax forms jsf jsf-2 viewstate

我有

<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?如何在不使用一个表单的情况下使其工作?这看起来像是一个JSF错误。我不想用

自动刷新该div
jQuery("#mydiv").load(document.location.href);

但在最糟糕的情况下我会这样做。

2 个答案:

答案 0 :(得分:22)

这是处理ajax响应的自动包含的jsf.js JSF库中的已知问题。另请参阅即将推出的JSF 2.3中修复的JSF spec issue 790。同时,使用JSF 2.0 / 2.1 / 2.2,您必须在<h:form>属性中明确指定其他render的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

另见:

答案 1 :(得分:0)

解决方法:

首先,您需要为发送ajax请求的按钮设置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("&lt;input type='hidden' name='javax.faces.ViewState' /&gt;").val(viewState);
        form.append(input);
    });
}
</h:outputScript>