JSF f:event preRenderView 是由 f:ajax 调用和部分渲染触发的,还有别的吗?

Posted

技术标签:

【中文标题】JSF f:event preRenderView 是由 f:ajax 调用和部分渲染触发的,还有别的吗?【英文标题】:JSF f:event preRenderView is triggered by f:ajax calls and partial renders, something else? 【发布时间】:2011-02-19 07:47:41 【问题描述】:

所以我们有一个 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 部分渲染时调用。我可以使用更合适的事件或方法吗?

【问题讨论】:

查看 Kawu 的回答:***.com/a/10363027/1599699 &lt;f:viewaction /&gt; 是一个很好的方法。 【参考方案1】:

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

【讨论】:

谢谢布赖恩,这些都是很好的建议。我今天将调查这两种途径。【参考方案2】:

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

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

【讨论】:

【参考方案3】:

这里描述了“新时代”的处理方式:

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

【讨论】:

如您所见,OP 有suggested 的扩展解释。看起来怎么样?我们通常会说:欢迎提供解决方案的链接,但请确保您的答案在没有它的情况下有用:add context around the link 这样您的其他用户就会知道它是什么以及为什么会出现,然后引用页面中最相关的部分如果目标页面不可用,您将链接到。 Answers that are little more than a link may be deleted.【参考方案4】:

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

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

FacesContext.getCurrentInstance().isPostback()

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

【讨论】:

【参考方案5】:

一个小问题是调用@PostConstruct 方法时没有设置视图参数,所以我必须显式获取它们:

FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("theParam");

【讨论】:

【参考方案6】:

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

boolean getMethod = ((HttpServletRequest) fc.getExternalContext().getRequest()).getMethod().equals("GET") ? true : false;
boolean ajaxRequest = fc.getPartialViewContext().isAjaxRequest();
boolean validationFailed = fc.isValidationFailed();

【讨论】:

【参考方案7】:

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

【讨论】:

以上是关于JSF f:event preRenderView 是由 f:ajax 调用和部分渲染触发的,还有别的吗?的主要内容,如果未能解决你的问题,请参考以下文章

JSF 2 事件列表?

将新组件动态添加到 JSF 组件树时重复 id

何时使用 preRenderView 与 viewAction?

何时使用 f:viewAction / preRenderView 与 PostConstruct?

查看 Scoped Bean preRenderView 方法被多次调用

有没有办法以编程方式检测用户何时按下浏览器中的F5按钮?