JSF f:event preRenderView 是由 f:ajax 调用和部分渲染触发的,还有别的吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2830834/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
JSF f:event preRenderView is triggered by f:ajax calls and partial renders, something else?
提问by Andrew
So we have an f:event:
所以我们有一个 f:event:
<f:metadata>
<f:event type="preRenderView" listener="#{dashboardBacking.loadProjectListFromDB}"/>
</f:metadata>
Which is triggered as desired on initial page load (render).
在初始页面加载(渲染)时根据需要触发。
However this preRenderView event is also triggered by an ajax partial page render, which re-renders an h:panelgroup with the id projectListing, as below.
然而,这个 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>
I only want the dashboardBacking.loadProjectListFromDB to be called for the initial page render, but not when there is an ajax partial render. Is there a more appropriate event or method I could be using?
我只想在初始页面呈现时调用dashboardBacking.loadProjectListFromDB,而不是在有ajax 部分呈现时调用。我可以使用更合适的事件或方法吗?
采纳答案by Brian Leathem
Another option would be to put your preRenderViewfunctionality in a @PostConstructmethod of a ViewScopedmanaged bean. This logic would be executed when the bean is initialized, and you you maintain the same instance of the bean for all your ajax requests until you change views.
另一种选择是将您的preRenderView功能放在托管 bean的@PostConstruct方法中ViewScoped。该逻辑将在 bean 初始化时执行,并且您为所有 ajax 请求维护相同的 bean 实例,直到您更改视图。
回答by Andre
I had the same need not too long ago. I ended up using something suggested by BalusC.
不久前我也有同样的需求。我最终使用了BalusC建议的东西。
There is a method in the FacesContext class that lets you know if you're dealing with a full blown request or a partial processing of some sort:
FacesContext 类中有一个方法可以让您知道您是在处理完整的请求还是某种类型的部分处理:
FacesContext.getCurrentInstance().isPostback()
This way you can still use the preRenderView technique and check if it's a postback in the listener. I found that particularly useful because I needed a session bean as the user had to navigate to another page and come back. If I used view scoped beans (like suggested above by Brian), I'd lose the info I had before navigating away.
这样您仍然可以使用 preRenderView 技术并检查它是否是侦听器中的回发。我发现这特别有用,因为我需要一个会话 bean,因为用户必须导航到另一个页面并返回。如果我使用视图范围的 bean(就像上面由 Brian 建议的那样),我会丢失导航之前的信息。
回答by Ryan
Another possibility is to check if the request is an ajax one or not in the preRenderView method. You can also perform the load conditionally considering other factors such as if the request is a GET or not and if validation failed or not (view params validation can fail on GET page).
另一种可能性是在 preRenderView 方法中检查请求是否是 ajax 请求。您还可以考虑其他因素有条件地执行加载,例如请求是否为 GET 以及验证是否失败(在 GET 页面上查看参数验证可能会失败)。
boolean getMethod = ((HttpServletRequest) fc.getExternalContext().getRequest()).getMethod().equals("GET") ? true : false;
boolean ajaxRequest = fc.getPartialViewContext().isAjaxRequest();
boolean validationFailed = fc.isValidationFailed();
回答by Kawu
The "new-age" way of handling this is described here:
此处描述了处理此问题的“新时代”方式:
http://www.coderanch.com/t/509746/JSF/java/duplicate-call-preRenderView-event#2634752
http://www.coderanch.com/t/509746/JSF/java/duplicate-call-preRenderView-event#2634752
回答by Brian Leathem
You could try attaching the preRenderView event listener to an individual component, rather than the page. Choose a component that is not rendered during an Ajax request.
您可以尝试将 preRenderView 事件侦听器附加到单个组件,而不是页面。选择在 Ajax 请求期间未呈现的组件。
回答by Manuel Palacio
One small problem is that the view parameters have not been set when the @PostConstruct method is called so I had to get them explicitly:
一个小问题是在调用@PostConstruct 方法时没有设置视图参数,所以我必须明确获取它们:
FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("theParam");
回答by Marcus Junius Brutus
update: actually, I ended up doing the @PostConstruct thing, its much cleaner.
更新:实际上,我最终做了@PostConstruct 的事情,它更干净了。
I had exactly the same issue today with a session-scoped backing bean. Namely, I had registered an event-listener method on the backing session-scoped bean that was registered with the preRenderView. But I found that it was also fired on some Ajax sorting operations on a PrimeFaces 3 dataTable component. So, what I ended up doing was using a boolean instance variable on the session-scoped backing bean to make sure the body of the event-listener method executed only the first time (the boolean acted as a flag). I am sure it's rather naive and probably broken on certain cases so I would be interested to know why and how this simplistic approach might fail.
我今天在会话范围的支持 bean 上遇到了完全相同的问题。也就是说,我在使用 preRenderView 注册的后备会话范围 bean 上注册了一个事件侦听器方法。但是我发现它也会在 PrimeFaces 3 dataTable 组件上的一些 Ajax 排序操作上被触发。所以,我最终做的是在会话范围的支持 bean 上使用一个布尔实例变量,以确保事件侦听器方法的主体仅在第一次执行(布尔值充当标志)。我确信它相当天真并且可能在某些情况下被破坏,所以我很想知道这种简单化的方法为什么以及如何失败。

