如何在RichFaces中实现纵向填充的双列dataGrid?
实现RichFaces纵向填充列的数据网格布局
问题描述
现有基于RichFaces的JSF页面,使用2列rich:dataGrid嵌套h:panelGrid展示数据,但当前布局为横向填满一行再换行:
Value1 Value2 Value3 Value4
需要改为先填充第一列(含列表半数内容),再填充第二列的纵向布局,最终效果:
Value1 Value3 Value2 Value4
同时需支持动态大小的列表(包括奇数个元素),询问是否可通过RichFaces实现。
现有代码
<fieldset> <legend>Select topics:</legend> <rich:dataGrid value="#{registerForm.topics}" var="topic" columns="2"> <h:panelGrid columns="2" width="430px" columnClasses="checkTopic,labelTopic" border="0"> <h:selectBooleanCheckbox id="checkTopic" align="left" value="#{registerForm.SelectedTopic}" disabled="#{not registerForm.ActiveRegister}"/> <h:outputLabel value="#{topic.description}" for="checkTopic" /> </h:panelGrid> </rich:dataGrid> <h:panelGroup rendered="#{empty registerForm.topics}" style="color: red;"> No topics registered. </h:panelGroup> </fieldset>
实现方案
核心思路
通过拆分原列表为左、右两个子列表,分别渲染到两列中,实现纵向填充的布局。无需依赖特殊标签,用JSF标准标签ui:repeat配合h:panelGrid即可实现,同时兼容RichFaces环境。
步骤1:后台Bean添加列表拆分逻辑
在registerForm对应的Managed Bean中,添加两个方法分别获取左列和右列的元素:
import java.util.Collections; import java.util.List; // 假设Topic是你的实体类 public List<Topic> getLeftColumnTopics() { List<Topic> topics = getTopics(); if (topics == null || topics.isEmpty()) { return Collections.emptyList(); } // 奇数个元素时左列多一个,保证布局平衡 int leftSize = (topics.size() + 1) / 2; return topics.subList(0, leftSize); } public List<Topic> getRightColumnTopics() { List<Topic> topics = getTopics(); if (topics == null || topics.isEmpty()) { return Collections.emptyList(); } int leftSize = (topics.size() + 1) / 2; return topics.subList(leftSize, topics.size()); }
步骤2:修改前端页面代码
用h:panelGrid创建2列容器,分别在左右列中用ui:repeat渲染对应子列表,确保每行元素纵向对齐:
<fieldset> <legend>Select topics:</legend> <!-- 外层2列容器 --> <h:panelGrid columns="2" width="860px" border="0" columnClasses="leftColumn,rightColumn"> <!-- 左列:渲染前半部分元素 --> <ui:repeat value="#{registerForm.leftColumnTopics}" var="topic"> <h:panelGrid columns="2" width="430px" columnClasses="checkTopic,labelTopic" border="0"> <h:selectBooleanCheckbox id="checkTopicLeft" align="left" value="#{registerForm.selectedTopics[topic.id]}" disabled="#{not registerForm.activeRegister}"/> <h:outputLabel value="#{topic.description}" for="checkTopicLeft" /> </h:panelGrid> </ui:repeat> <!-- 右列:渲染后半部分元素 --> <ui:repeat value="#{registerForm.rightColumnTopics}" var="topic"> <h:panelGrid columns="2" width="430px" columnClasses="checkTopic,labelTopic" border="0"> <h:selectBooleanCheckbox id="checkTopicRight" align="left" value="#{registerForm.selectedTopics[topic.id]}" disabled="#{not registerForm.activeRegister}"/> <h:outputLabel value="#{topic.description}" for="checkTopicRight" /> </h:panelGrid> </ui:repeat> </h:panelGrid> <h:panelGroup rendered="#{empty registerForm.topics}" style="color: red;"> No topics registered. </h:panelGroup> </fieldset>
关键注意事项
- 修复复选框绑定问题:原代码中所有复选框绑定到同一个
SelectedTopic属性,会导致选中状态互相覆盖。建议改用Map<Long, Boolean>(根据Topic的ID类型调整键的类型)存储每个主题的选中状态,后台Bean需添加对应属性及getter/setter。 - 奇数元素兼容:拆分列表时用
(topics.size() + 1) / 2计算左列长度,确保奇数个元素时左列比右列多一个,避免右列出现空白行。 - 样式兼容:若需保留
rich:dataGrid的样式,可将左右列的ui:repeat替换为rich:dataGrid columns="1",保持样式一致性。
内容的提问来源于stack exchange,提问作者hmpm
相关产品推荐
相关产品推荐

