JSF 生命周期问题:在应用请求属性之前构建组件树

发布于 2024-11-25 15:45:48 字数 1048 浏览 1 评论 0原文

我有一个 JSF 2.0 Facelets 视图,其中包含搜索表单、用于显示结果的 ui:repeat 和寻呼机。它由请求 bean 支持。表单帖子由当前页面和搜索条件组成。分页器根据数据集中的位置以及使用表单中的搜索条件进行查询的结果数量显示下一页和上一页链接。 因此组件树依赖于请求属性。例如,我在下一页链接上使用呈现的属性,如下所示

<h:commandLink action="#{listBean.nextPage}" rendered="#{listBean.hasNextPage}" >...

当用户单击此链接时,POST 请求包含当前页面和搜索条件。问题是,组件树已经在 RESTORE_VIEW 中构建。此时,由于尚未应用请求属性,因此我既无法判断用户当前位于哪个页面,也无法判断数据集中有多少条记录,因为我没有搜索条件。因此 listBean.hasNextPage 在此阶段的计算结果为 false。这似乎导致 CommandLink 从组件树中消失。在 APPLY_REQUEST_VALUES 之后,我可以构建我的计数查询。有了这些信息和当前页面,我就可以计算出 listBean.hasNextPage。但是,在 RENDER_RESPONSE 之前似乎不会再次对其进行评估。该操作根本不会在 INVOKE_APPLICATION 中被调用。而且也没有错误,这很烦人。

当用 c:if 替换渲染时它可以工作。 c:if 仅在 RENDER_RESPONSE 中计算一次,并且默认情况下该组件位于第一阶段的树中。我真的不喜欢它,因为在(罕见的,承认的)情况下,数据集计数发生变化,因此实际上没有下一页,它仍然会调用该操作,并且用户将处于非法页面中。据我所知,通常不建议在 Facelets 中使用 JSTL 标签。我不知道为什么。

是否有任何技巧可以将渲染评估延迟到 APPLY_REQUEST_VALUES 之后?必须有一种方法可以在依赖于当前请求的属性上使用此属性。 仅供参考,这是 Liferay 上的一个带有 JBoss portlet 桥的 portlet 2.0 应用程序,但我猜这是一个通用的 JSF 问题。

预先感谢您的任何答复。我希望我只是忽略了一些东西,我仍在学习 JSF - 编写寻呼机并不难,对吧:-)

I have a JSF 2.0 facelets view containing of a search form, an ui:repeat for displaying results, and a pager. It is backed by a request bean. The form post consists of the current page, and the search criteria. The pager shows next and previous page links depending on the position in the dataset, and the numberof results from the query with the search criteria from the form.
So the component tree is dependant on request attributes. For example, I'm using the rendered attribute on the next page link like this

<h:commandLink action="#{listBean.nextPage}" rendered="#{listBean.hasNextPage}" >...

When the user clicks this link, the POST request contains the current page, and the search criteria. The problem is, that the component tree is already build in RESTORE_VIEW. In this moment, because request attributes have not been applied yet, I can neither tell on which page the user is currently, or how many records are in the dataset because i don't have the search criteria. So listBean.hasNextPage evaluates to false in this phase. This seems to cause that the CommandLink disappears from the component tree. After APPLY_REQUEST_VALUES I'm able to construct my count query. With this information and the current page, I could calculate listBean.hasNextPage. However, it doesn't seem to get evaluated again until RENDER_RESPONSE. The action does not get called in INVOKE_APPLICATION at all. Also there is no error, which is annoying.

It works when replacing rendered with c:if. c:if is only evaluated in RENDER_RESPONSE once, and the component is in the tree in the first phases by default. I don't really like it, because in the (rare, admitted) case, that the dataset count changes so that there is in fact no next page, it would still call the action and the user would be in an illegal page. Also I understand using JSTL tags in Facelets is commonly advise against. I don't know why.

Is there any trick to have rendered evaluation delayed until after APPLY_REQUEST_VALUES? There must be a way to use this attribute on properties that are dependant on the current request.
Just FYI, this is a portlet 2.0 app on Liferay with the JBoss portlet bridge, but I guess it's a generic JSF problem.

Thanks in advance for any answers. I hope I'm just overlooking something, I'm still learning JSF - I can't be that hard to write a pager, right :-)

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

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

发布评论

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

评论(1

顾忌 2024-12-02 15:45:48

从您的描述来看,您似乎认为您在新请求(回发)开始时需要新数据集,但事实并非如此。

RESTORE_VIEW 期间直到 INVOKE_APPLICATION,您需要拥有用于呈现用户刚刚单击的页面的可用数据集,而不是将用于呈现当前请求的一个。

实现此目的的最简单方法是使您的支持 bean @ViewScoped 并通过实例变量保存对数据集的引用。回发后,JSF 将自动保留“旧”数据集并将其用于生命周期的第一部分。然后,在 INVOKE_APPLICATION 中,您拥有加载下一页的所有数据,从而为 hasNextPage 设置“新”数据集和布尔值。

然后,RENDER_RESPONSE 将使用新值发生并呈现您的新页面。

From your description it seems that you think you need the new dataset at the start of the new request (the postback), but this is not the case.

During RESTORE_VIEW up until INVOKE_APPLICATION you need to have the dataset available that was used to render the page on which the user has just clicked, not the one that is going to be used to render the current request.

The easiest way to achieve this is to make your backing bean @ViewScoped and hold a reference to the dataset via an instance variable. After the postback, JSF will then automatically retain the 'old' dataset and use this for the first part of the life cycle. Then in INVOKE_APPLICATION you have all the data to load your next page and thus set the 'new' dataset and boolean for hasNextPage.

RENDER_RESPONSE will then happen with the new values and will render your new page.

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