[英]Why does <ui:repeat> not work with java.util.Iterator?
Why does JSF2/Facelet's ui:repeat not accept java.util.Iterator's for value? 为什么JSF2 / Facelet的ui:repeat不接受java.util.Iterator的值? One can hide so much implementation and memory conservation behind an Iterator since length need not be known, it would be so useful to have.
因为不需要知道长度,所以可以在Iterator后面隐藏这么多的实现和内存保存,拥有它会非常有用。 But instead I need to convert my Iterators to Lists and throw away all my advantages in order to ui:repeat.
但是相反,我需要将Iterators转换为Lists并放弃所有优点,以便使用ui:repeat。
There are probably phase or timing or Serializable reasons, but my skimming of the docs that are available do not give those reasons. 可能有阶段或时序或可序列化的原因,但是我对可用文档的略读并没有给出这些原因。 Do we not yet have the science to make this impossibility possible?
我们是否还没有使这种可能性成为可能的科学?
<ui:repeat>
doesn't support java.util.Iterator
. <ui:repeat>
不支持java.util.Iterator
。
Have look at UIRepeat.getDataModel()
source code: 看一下
UIRepeat.getDataModel()
源代码:
private DataModel getDataModel() {
if (this.model == null) {
Object val = this.getValue();
if (val == null) {
this.model = EMPTY_MODEL;
} else if (val instanceof DataModel) {
//noinspection unchecked
this.model = (DataModel<Object>) val;
} else if (val instanceof List) {
//noinspection unchecked
this.model = new ListDataModel<Object>((List<Object>) val);
} else if (Object[].class.isAssignableFrom(val.getClass())) {
this.model = new ArrayDataModel<Object>((Object[]) val);
} else if (val instanceof ResultSet) {
this.model = new ResultSetDataModel((ResultSet) val);
} else {
this.model = new ScalarDataModel<Object>(val);
}
}
return this.model;
}
You can make <ui:repeat> work with an Iterator, but you must wrap the Iterator with an object that extends javax.faces.model.DataModel. 您可以使<ui:repeat>与Iterator一起使用,但是必须用扩展javax.faces.model.DataModel的对象包装Iterator。 Here is my IteratorDataModel class that can make any Iterator accessible to <ui:repeat>.
这是我的IteratorDataModel类,可以使<ui:repeat>可以访问任何迭代器。 I tested this with JSF 2.1.26:
我使用JSF 2.1.26对此进行了测试:
/**
* Make a DataModel out of an Iterator that may be used with JSF's ui:repeat tag
*
* This DataModel does not support the use of offset or step attributes in the
* ui:repeat tag, and the size attribute in ui:repeat, when used with this DataModel,
* will report an inaccurate value.
*
* Copyright (c) 2014 Woldrich, Inc.
* Licensed under MIT (https://clubcompy.com/wcm/license/mit.txt)
*
* @author Dave Woldrich
*/
public class IteratorDataModel<T> extends DataModel<T> {
private static final Logger logger = LogManager.getLogger(IteratorDataModel.class);
private Iterator<?> iterator;
private int rowIndex;
private T item;
public IteratorDataModel(Iterator<?> iterator) {
setWrappedData(iterator);
}
@Override
public int getRowCount() {
return Integer.MAX_VALUE;
}
@Override
public T getRowData() {
return this.item;
}
@Override
public int getRowIndex() {
if(this.rowIndex == -1 && this.iterator.hasNext()) {
this.setRowIndex(0);
}
if(logger.isTraceEnabled()) {
logger.trace("getRowIndex returns " + this.rowIndex);
}
return this.rowIndex;
}
@Override
public Object getWrappedData() {
return this.iterator;
}
@Override
public boolean isRowAvailable() {
boolean hasNext = this.item != null || this.iterator.hasNext();
if(logger.isTraceEnabled()) {
logger.trace("isRowAvailable " + hasNext);
}
return hasNext;
}
@SuppressWarnings("unchecked")
@Override
public void setRowIndex(int newIndex) {
if(logger.isTraceEnabled()) {
logger.trace("setRowIndex (" + newIndex + ")");
}
if(newIndex == this.rowIndex+1) {
this.rowIndex = newIndex;
this.item = (T) (this.iterator.hasNext() ? this.iterator.next() : null);
}
else if(newIndex > -1 || newIndex != this.rowIndex) {
if(logger.isTraceEnabled()) {
logger.trace("setRowIndex not incrementing by 1 as expected, ignored");
}
}
}
@Override
public void setWrappedData(Object data) {
this.iterator = (Iterator<?>) data;
this.rowIndex = -1;
this.item = null;
}
}
And in your facelets code, for example, you may use: 例如,在facelets代码中,您可以使用:
<ul>
<ui:repeat value="#{chatRoom.allComments}" var="aComment" varStatus="status">
<li><h:outputText value="#{aComment.text}" /></li>
</ui:repeat>
</ul>
where chatRoom.getAllComments() would return a IteratorDataModel<Comment>
that is constructed passing an Iterator<Comment>
. 其中chatRoom.getAllComments()将返回通过
IteratorDataModel<Comment>
构造的Iterator<Comment>
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.