25

所以我们有一个 f:event:

   <f:metadata>
    <f:event type="preRenderView" listener="#{dashboardBacking.loadProjectListFromDB}"/>
   </f:metadata>

在初始页面加载(渲染)时根据需要触发。

然而,这个 preRenderView 事件也是由 ajax 部分页面渲染触发的,它重新渲染一个带有 id projectListing 的 h:panelgroup,如下所示。

<h:commandButton action="#{mrBean.addProject}" value="Create Project"
                                     title="Start a new project">
   <f:ajax render="projectListing" />
</h:commandButton>

我只希望为初始页面渲染调用dashboardBacking.loadProjectListFromDB,而不是在有ajax 部分渲染时调用。我可以使用更合适的事件或方法吗?

4

7 回答 7

31

不久前我也有同样的需要。我最终使用了BalusC建议的东西。

FacesContext 类中有一个方法可以让您知道您是在处理完整的请求还是某种类型的部分处理:

FacesContext.getCurrentInstance().isPostback()

这样,您仍然可以使用 preRenderView 技术并检查它是否是侦听器中的回发。我发现这特别有用,因为我需要一个会话 bean,因为用户必须导航到另一个页面并返回。如果我使用视图范围的 bean(就像上面 Brian 建议的那样),我会丢失我在离开之前拥有的信息。

于 2011-10-15T16:09:15.973 回答
11

另一种选择是将您的preRenderView功能放在托管 bean的@PostConstruct方法中。ViewScoped此逻辑将在 bean 初始化时执行,并且您为所有 ajax 请求维护 bean 的相同实例,直到您更改视图。

于 2010-05-18T14:58:01.147 回答
7

另一种可能性是在 preRenderView 方法中检查请求是否是 ajax 请求。您还可以有条件地执行加载,考虑其他因素,例如请求是否为 GET 以及验证是否失败(查看参数验证可能在 GET 页面上失败)。

boolean getMethod = ((HttpServletRequest) fc.getExternalContext().getRequest()).getMethod().equals("GET") ? true : false;
boolean ajaxRequest = fc.getPartialViewContext().isAjaxRequest();
boolean validationFailed = fc.isValidationFailed();
于 2010-11-15T15:10:16.690 回答
2

此处描述了处理此问题的“新时代”方式:

http://www.coderanch.com/t/509746/JSF/java/duplicate-call-preRenderView-event#2634752

于 2012-04-28T11:22:30.397 回答
1

您可以尝试将 preRenderView 事件侦听器附加到单个组件,而不是页面。选择在 Ajax 请求期间未呈现的组件。

于 2010-05-18T05:39:53.250 回答
0

更新:实际上,我最终做了@PostConstruct 的事情,它更干净。

我今天在会话范围的支持 bean 上遇到了完全相同的问题。即,我在使用 preRenderView 注册的支持会话范围 bean 上注册了一个事件侦听器方法。但我发现它也在 PrimeFaces 3 dataTable 组件上的一些 Ajax 排序操作上被触发。所以,我最终做的是在会话范围的支持 bean 上使用一个布尔实例变量,以确保事件监听器方法的主体仅在第一次执行(布尔充当标志)。我确信它相当幼稚并且可能在某些情况下被打破,所以我很想知道这种简单的方法为什么以及如何失败。

于 2012-07-19T07:06:34.920 回答
0

一个小问题是调用@PostConstruct 方法时视图参数尚未设置,因此我必须显式获取它们:

FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("theParam");
于 2011-02-08T08:48:35.237 回答