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

发布于 2024-12-10 10:29:05 字数 975 浏览 1 评论 0原文

当我

<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 bug。我不想自动刷新该 div

jQuery("#mydiv").load(document.location.href);

,但在最坏的情况下我会这样做。

I have

<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>

When I click once on "my_fake_ajax_link", then I have to click twice on "delete" link. This is only an example. I don't have this real case. I have multiple forms on a page and I can't just add all of them in a single form.

I checked what the problem is and it is:

  • When you click on "my_fake_ajax_link", the mydiv refreshs with ajax as it should.
  • ViewState of the refreshed form on ajax is missing.

How can I add the ViewState? How can I make it work without using only one form? This looks like an JSF bug to me. I don't want to refresh that div automatically with

jQuery("#mydiv").load(document.location.href);

but I will in my worst case possible.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

玩世 2024-12-17 10:29:05

这是处理 ajax 响应的 JSF 自动包含的 jsf.js 库中的一个已知问题。另请参阅 JSF 规范问题 790,该问题已在即将发布的 JSF 2.3 中修复。同时,在 JSF 2.0/2.1/2.2 中,您必须在 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

另请参阅:

This is a known problem in the auto-included jsf.js library of JSF which handles ajax responses. See also JSF spec issue 790 which is fixed in the upcoming JSF 2.3. In the meanwhile, with JSF 2.0/2.1/2.2, you have to explicitly specify the ID of the other <h:form> inside the render attribtue to trigger proper addition of the view state.

<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>

No, this does not cause any overhead or markup duplication in the ajax response. Alternatively, use OmniFaces fixviewstate.js.

See also:

无名指的心愿 2024-12-17 10:29:05

解决方法:

首先,您需要为发送 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("<input type='hidden' name='javax.faces.ViewState' />").val(viewState);
        form.append(input);
    });
}
</h:outputScript>

Workaround for that:

First you need to set an onevent handler for the button that sends the ajax request:

<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>

Then you need to declare this javascript methods that will take the correct viewState value and add it to all forms which doesn't have it:

<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>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文