1

我有一个 JSF 页面,其中包含一些常见元素,然后是 4 个根据各种用户操作动态加载和包含的部分。我有封装各种包含功能的 bean,结构如下所示:

mainview.xhtml 
     --backed by--> mainViewBean (request scope) 
       --with managed property--> mainViewView (view scope)

include1.xhtml
     --backed by--> include1Bean (request scope)
       --with managed property--> mainViewBean

include2.xhtml
     --backed by--> include2Bean (request scope)
       --with managed property--> mainViewBean

include3.xhtml
     --backed by (and with component bindings to)--> include3Bean (request scope)
       --with managed property--> mainViewBean

include4.xhtml
     --backed by--> mainViewBean

在主视图页面上,每个包含都通过一系列条件渲染的 h:panelGroups 包含在 BalusC 在这些问题中的描述中:

https://stackoverflow.com/a/9897016/945403

https://stackoverflow.com/a/7113961/945403

视图范围 bean 包含一些关于用户活动的当前状态、他们当前正在查看的项目等的各种视图信息。

每个包含的视图都通过 ajax 和非 ajax 帖子执行各种任务。我的问题是某些面板中的某些操作似乎会导致视图范围被破坏,并且似乎没有押韵或理由。对于下面概述的错综复杂的工作流程,我提前道歉,但我会尽量做到清楚。

如果我在 include3.xhtml 中执行 ajax 操作,它们只会在 include 中呈现组件,我可以整天这样做,并且视图范围仍然存在。如果我执行非 ajax 帖子,刷新将更新(并可能添加以前未渲染的)include4.xhtml。然后,我可以随后在任何其他包含中执行操作。

如果我在 include1.xhtml 中执行一个 ajax 操作,它只调用它自己的支持 bean 中的方法,并且只更新它自己的组件,那么视图范围仍然存在。如果我执行调用 include3Bean 中的方法并更新包含 include2.xhtml 和 include3.xhtml 的 div 的 ajax 操作,则视图范围仍然存在,只要我继续在 include1.xhtml 中执行操作,视图范围就会保留。一旦我尝试在另一个包含中执行另一个操作,视图范围就会被破坏。

在这一点上,我对自己认为问题一定在于我正在更新不同的包含,而不是从中调用操作。但这似乎不是问题(或至少是唯一的问题),我现在将解释。

include2.xhtml 有一个 ajax 动作,当它被触发时,调用 mainViewBacking 中的一个方法并更新包含 include2.xhtml 和 include3.xhtml 的 div。如果我继续执行此操作,或在 include2.xhtml 中执行任何其他操作(包括非 ajax 操作),一切都会按预期工作并且视图范围仍然存在。但是,如果我随后在 include3.xhtml 中执行操作,则视图范围被破坏。奇怪的是我可以在 include1.xhtml 中执行操作,只要我愿意,他们将继续访问视图范围,但如果我尝试返回并在 include2.xhtml 或 include3 中执行操作。 xhtml,视图范围再次丢失。

我在这一点上有点卡住了,我什至不知道如何去找出问题所在。我假设一些关于刷新(以及删除或添加)包含的内容会导致视图范围丢失,但从之前链接的问题来看,这似乎不是问题,因为 ui 的实际 src 值:includes 不是动态生成的。而且我确实关闭了 mainview.xhtml 的部分状态保存。

这些动态显示的 ui:includes 有什么东西会破坏视图范围吗?

4

1 回答 1

3

编辑 2014-02-28:

在查看最新的omnifaces 展示时,我注意到BalusC 已经实现了一个脚本,它应该可以解决同样的问题,并且可能以比我下面的代码更好的方式来完成它。

http://showcase.omnifaces.org/scripts/FixViewState

原答案:

事实证明,这是 BalusC 在此处描述的 JSF 中的一个错误:http: //balusc.blogspot.com/2011/09/communication-in-jsf-20.html#AjaxRenderingOfContentWhichContainsAnotherForm

不幸的是,由于某种原因,他的解决方案对我来说并没有始终如一地工作。结果,我编写了自己的(稍微烦人的)工作,如果他们需要,我会在这里提供给其他人。

我将以下 javascript 添加到 mainview.xhtml 页面:

var lastForm = null;

        function getViewStateFromLastForm(callingElement){

            var currentForm = $(callingElement).closest("form");
            var formId = currentForm.attr("id");

            if(lastForm != null ){
                var viewState = $("#" + lastForm).children("[name='javax.faces.ViewState']").val();
                currentForm.children("[name='javax.faces.ViewState']").remove();

                $('<input/>').attr({
                    type: 'hidden',
                    id: 'javax.faces.ViewState',
                    name: 'javax.faces.ViewState',
                    autocomplete: 'off',
                    value: viewState
                }).appendTo(currentForm);
            }
            lastForm = formId;

        }

然后,提交给服务器的各个包含页面上的每个按钮getViewStateFromLastForm(this);在其 onclick 属性中都有一个调用。

于 2012-09-20T14:37:51.877 回答