使用 JSF ui:repeat 循环执行带状态的逻辑

Posted

技术标签:

【中文标题】使用 JSF ui:repeat 循环执行带状态的逻辑【英文标题】:Performing logic with state with a JSF ui:repeat loop 【发布时间】:2015-03-29 21:02:34 【问题描述】:

我是 JSF / Facelets 的新手,在决定是否在 ui:repeat 组件中呈现内容时,我试图了解最适合放置逻辑的位置。

在我的支持 bean 中,我有一个消息列表,每个消息都包含一个日期。我想打印所有消息,但只在日期发生变化时呈现日期。

目前我有类似下面的内容,其中支持 bean getter 方法根据支持 bean 中的逻辑和设置状态确定是否呈现消息日期。

<ui:repeat value="#bean.orderedMessages" var="message" varStatus="messageLoop">

    <h:panelGroup rendered="#bean.isDateRendered(messageLoop.index)">
       #message.formattedDate
    </h:panelGroup>

    // some other stuff for each message

</ui:repeat>

这是错误和可怕的,因为 JSF 在实际渲染之前多次调用 getter 方法,这进一步增加了 getter 方法的复杂性,除了是否应该渲染某些东西之外,代码与其他任何事情都没有关系。在 UI 中,getter 方法中有一大堆讨厌的逻辑,而我更喜欢返回一个简单的属性。

我认为 UI 必须以某种方式存储上次渲染日期的状态,并将其与即将渲染的日期进行比较,但我不确定这是否正确。

我不认为这是一个不常见的问题。有谁知道是否有更优雅的解决方案来解决这个问题?

【问题讨论】:

此实例中的消息是从数据库填充的实体。它总是会被渲染,但有一个属性(日期),它可能会或可能不会在运行时纯粹与列表中的其他消息相关。我认为逻辑不应该存在于消息实体中,因为这是一个 UI 事物,并且消息也不知道其他消息。这个问题与管理重复中对象的状态问题以及如何管理该状态有关。 可能 JSF 应该在后台 bean 上调用 <:c:set...> 来设置最后呈现的日期。不确定这是否是一种好习惯,因为感觉不太好。 【参考方案1】:

根据BalusC在问题的cmets中提出的想法,我实现了以下解决方案。

我的来自实体/域层的Message对象在创建实例@PostConstuct时返回到支持bean,我在UI层中创建了另一个模型UIAugmentedMessage,它采用Message构造函数以及 isRendered 的布尔属性和格式化日期的字符串。

Message 列表在 bean 刚刚构建后从服务器返回时,支持 bean 构建 UIAugmentedMessage 对象列表,其中包含 isRendered 和 formattedDate 字段的正确状态。

UI层现在简化如下

<ui:repeat value="#bean.orderedMessages" var="message">

    <h:panelGroup rendered="#message.rendered">
       #message.formattedDate
    </h:panelGroup>

</ui:repeat>

【讨论】:

以上是关于使用 JSF ui:repeat 循环执行带状态的逻辑的主要内容,如果未能解决你的问题,请参考以下文章

如何在没有 JSF 标记库(h:datatable 或 ui:repeat)的情况下编写 <table> 标记,但仍使用 JSF 来控制页面流

JSF <ui:repeat> <c:forEach> 复合 UINamingContainer

使用 ui:repeat 输出 ResultSet

没有dataModel的JSF 2 dataTable行索引

有条件地渲染 tr,使用 ui:repeat 构建表

使用 ui:repeat 和 b:carousel?