JSF 2.0的ui:repeat标记获取javabean(arraylist)的值作为它的value属性,但size属性没有。我在一个数据表中使用ui repeat,它迭代地显示状态,ui repeat显示每个状态的注释。我从一个java类中给出ui repeat的size属性,因为每个状态都有不同数量的注释。因此,大小应该动态决定。这是我所做的总结。型号类别:
@ManagedBean
@RequestScoped
public class Comment {
private String commentAuthorName;
//getter and setter
}
这表示Status类,它有一个注释列表:
@ManagedBean
@RequestScoped
public class Status {
private ArrayList<Comment> commentList;
private int numOfComments;
//getter and setter
}
这是关于StatusBean类的一个想法:
@ManagedBean
@SessionScoped
public class StatusBean {
List<Status> panelList = new ArrayList<Status>();
List<Comment> commentList = new ArrayList<Comment>();
public static void process() {
panelList = StatusService.getPersonalStatus(log.getLoggeduser());//means fill list
commentList = StatusService.getPersonalComments(panelList);//gets comments via related statuses
for (int i=0; i<panelList.size(); i++) { //for each status
Status status = panelList.get(i);
for(Comment comment : commentList) { //for each comment of each status
status.setNumOfCommentsShown(1);
}
}
}
}
而视图层是类似下面的东西。Ui重复包含在PrimeFaces DataTable中,以便能够显示每个状态的每个注释。我使用datatable是因为它有实时滚动,必须迭代显示所有状态,而ui repeat看起来最适合显示每个状态的每个注释。
<p:dataTable liveScroll="true" value="#{StatusBean.panelList}"
var="Status" scrollable="true">
<ui:repeat var="Comment" value="#{Status.commentList}"
size="#{Status.numOfComments}"></ui:repeat>
</p:dataTable>
调试结果显示#{Status.numOfComments}正确填充了所需的整数,但仍然不起作用。但是,如果我手动写入size=3,它会给出预期的结果。
据我所知,到今天为止还没有答案,所以我会回答你的问题,并告诉你我肯定会在你的堆栈中改变什么。
分析您的问题
关于使用托管bean属性指定的具有size
属性的<ui:repeat>
,我已经编写了与您类似的代码,但它对我也不起作用。无论我多么努力地通过EL设置属性的值,它都不起作用。此外,它也不适用于像#{5}
这样的最简单的EL。我不知道这个问题是从哪里来的,但我认为这里的经历会启发我们为什么会发生这种情况,是吗?
也许这是JSF <ui:repeat>
组件的一个小故障,那么我们将提出一个关于它的问题。如果这是一个特性,那么完全理解它就好了。
据我所知,这是您代码的一个工作示例
关于上面的代码,有许多简单的解决方法。如果您坚持使用<ui:repeat>
组件,我将为您提供基本的工作示例。您的视图层由一个JSF管理的bean和两个模型类支持。我的解决方案使用<ui:param>
和<ui:fragment>
。我们开始吧。
视图:
<p:dataTable value="#{statusBean.statusesList}" var="status">
<p:column headerText="Status name">
<h:outputText value="#{status.statusName}"/>
</p:column>
<p:column headerText="Status comments">
<ul>
<ui:param name="max" value="#{status.numOfComments}"/>
<ui:repeat var="comment" value="#{status.commentList}" varStatus="statusVar">
<ui:fragment rendered="#{statusVar.index lt max}">
<li>
<h:outputText value="Author: #{comment.authorName}; comment: #{comment.description}"/>
</li>
</ui:fragment>
</ui:repeat>
</ul>
</p:column>
</p:dataTable>
型号:
public class Comment {
private String authorName;
private String description;
}
带有
public class Status {
private List<Comment> commentList;
private int numOfComments;
private String statusName;
}
托管bean:
@ManagedBean
@RequestScoped
public class StatusBean {
private List<Status> statusesList;
public StatusBean() {
Status status;
List<Status> statusesList = new ArrayList<Status>();
Comment comment;
List<Comment> commentList;
for(int s = 0; s < 10; s++) {
commentList = new ArrayList<Comment>();
for(int c = 0; c < 20; c++) {
commentList.add(new Comment("User " + (s + 1) + "-" + (c + 1), "Description for comment " + (s + 1) + "-" + (c + 1)));
}
statusesList.add(new Status(commentList, (s + 1), "Status " + (s + 1)));
}
this.statusesList = statusesList;
}
}
我肯定会在你的代码中更改的内容
在代码工作之后,我想说明我将要做的一些改进。
- 使您的模型成为模型:去掉
@ManagedBean
和@...Scoped
注释,改为使它们(分离的)@Entity
类,由您的服务bean进行研究 - 尽量使模型尽可能简单,同时保留应用程序的功能。我的示例只使用一个状态列表作为bean中的数据持有者:您不需要一个重复的注释列表,因为它已经存在于
Status
对象中 - 不要在bean中使用静态方法,而是在页面操作方法(Servlet 3.0)、
preRenderView
侦听器(Servlet 2.5)或@PostConstruct
方法中(预)加载必要的数据。选择好bean作用域。咨询BalusC的优秀概览将是一个很好的起点 - 使用服务方法调用只从数据源预加载您需要的数据:如果您愿意显示有限数量的注释,为什么要从数据源中获取它们?根据您的需要限制结果集(记住,如果您想实现"查看所有"功能,您可以使用ajax更新元素并加载其余元素)。使其以这种方式工作消除了使用
size="..."
的需要 - 使用标准的UI组件或您选择的组件库的组件,即Primefaces,所以请尝试遵循Luiggi Mendoza的建议
托管bean的启动示例如下:
@ManagedBean
@RequestScoped
public class StatusBean {
private List<Status> statusesList;
@EJB
private StatusService statusService;
@ManagedProperty(value="#{user}")
private User user;
@PostConstruct
public void init() {
statusesList = statusService.getStatuses(user);
}
public List<Status> getStatusesList() {
return statusesList;
}
}