我有一个可分页和可排序的<p:dataTable>
:
<p:dataTable var="item" value="#{reporteIngresosPorExtranetController.detalle}"
paginator="true" rows="10" paginatorPosition="bottom" rowsPerPageTemplate="5,10,15"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}">
<p:column sortBy="#{item.user}" headerText="USUARIO:">
<h:outputText value="#{item.user}" />
</p:column>
...
</p:dataTable>
在preRenderView
事件期间,其数据从闪存示波器获取到@ViewScoped
Bean 中:
<f:event type="preRenderView" listener="#{reporteIngresosPorExtranetController.cargarDatos}" />
public void cargarDatos() {
detalle = (List<Map<String, Object>>) FacesUtils.flashScope().get("RIE_detalle");
}
当我执行分页或排序时,数据会丢失。这是如何造成的,我该如何解决?
您似乎认为在创建视图范围期间仅执行一次preRenderView
。这是错误的。preRenderView
在每个 HTTP 请求期间执行,就在呈现视图之前(再次读取事件名称,现在应该更有意义了,对吧?分页和排序由 ajax 执行。每个 ajax 请求也被视为 HTTP 请求。Flash 范围的数据的生存期只有一个重定向。Flash 范围数据不再可用于所有后续请求,除非再次在 flasch 作用域中显式设置。所以基本上,你的侦听器方法在每个分页和排序请求上都会被重新调用,从而有效地将detalle
设置为null
。
完全摆脱<f:event>
,并在方法上放置@PostConstruct
注释。这样,在创建视图范围期间,它实际上只调用一次,完全符合您的意图。
@PostConstruct
public void cargarDatos() {
detalle = (List<Map<String, Object>>) FacesUtils.flashScope().get("RIE_detalle");
}
另请参阅:
- 何时使用 f:viewAction/preRenderView 与 PostConstruct?
与具体问题无关,这个设计是...有点奇怪。我真的会咨询一个更有经验的JSF架构师,了解如何正确实现具体的功能需求,你可能错误地认为以这种方式使用闪存示波器是正确的方法。