所以我们有一个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部分渲染时则不需要。我可以使用更合适的事件或方法吗?
答案 0 :(得分:31)
我不久前也有同样的需要。我最终使用了BalusC建议的内容。
FacesContext类中有一个方法可以让您知道您是在处理完整的请求还是某种部分处理:
FacesContext.getCurrentInstance().isPostback()
这样你仍然可以使用preRenderView技术并检查它是否是监听器中的回发。我发现这特别有用,因为我需要一个会话bean,因为用户必须导航到另一个页面并返回。如果我使用了视图范围的bean(就像Brian上面提到的那样),我会在导航之前丢失我的信息。
答案 1 :(得分:11)
另一种选择是将preRenderView
功能放在@PostConstruct
托管bean的ViewScoped
方法中。初始化bean时将执行此逻辑,并且在更改视图之前为所有ajax请求维护相同的bean实例。
答案 2 :(得分: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();
答案 3 :(得分:2)
此处描述了处理此问题的“新时代”方式:
http://www.coderanch.com/t/509746/JSF/java/duplicate-call-preRenderView-event#2634752
答案 4 :(得分:1)
您可以尝试将preRenderView事件侦听器附加到单个组件,而不是页面。选择在Ajax请求期间未呈现的组件。
答案 5 :(得分:0)
一个小问题是,在调用@PostConstruct方法时尚未设置视图参数,因此我必须明确地获取它们:
FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("theParam");
答案 6 :(得分:0)
更新:实际上,我最终做了@PostConstruct的事情,它更干净了。
今天我遇到了与会话范围的支持bean完全相同的问题。也就是说,我在使用preRenderView注册的后备会话范围bean上注册了一个事件监听器方法。但我发现它也在PrimeFaces 3 dataTable组件上的一些Ajax排序操作上被触发。所以,我最终做的是在会话范围的辅助bean上使用布尔实例变量,以确保事件监听器方法的主体仅在第一次执行时(布尔作为标志)。我确信这是相当天真的,并且可能在某些情况下被打破,所以我有兴趣知道为什么以及如何这种简单化的方法可能会失败。