如何为h:dataTable/ui:repeat的每一行/项目设置转换器属性? [英] How to set converter properties for each row/item of h:dataTable/ui:repeat?
问题描述
我创建了一个自定义ISO日期时间Converter
:
I have created a custom ISO date time Converter
:
public class IsoDateTimeConverter implements Converter, StateHolder {
private Class type;
private String pattern;
private boolean transientValue = false;
public void setType(Class type) {
this.type = type;
}
public void setPattern(String pattern) {
this.pattern = pattern;
}
@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) throws ConverterException {
if (StringCheck.isNullOrEmpty(value)) {
throw new ConverterException("value not specified");
}
try {
if (IsoDate.class.equals(type)) {
if (WebConst.ISO_DATE_NONE.equals(value)) {
return IsoDate.DUMMY;
} else {
//TODO User spezifische TimeZone auslesen
return new IsoDate(value, TimeZone.getDefault().getID());
}
} else if (IsoTime.class.equals(type)) {
if (WebConst.ISO_TIME_NONE.equals(value)) {
return IsoTime.DUMMY;
} else {
//TODO User spezifische TimeZone auslesen
return new IsoTime(value, TimeZone.getDefault().getID());
}
} else if (IsoTimestamp.class.equals(type)) {
if (WebConst.ISO_TIMESTAMP_NONE.equals(value)) {
return IsoTimestamp.DUMMY;
} else {
//TODO User spezifische TimeZone auslesen
return new IsoTimestamp(value, TimeZone.getDefault().getID());
}
} else {
throw new ConverterException("value not convertible");
}
} catch (Exception e) {
throw new ConverterException(e.getMessage());
}
}
@Override
public String getAsString(FacesContext context, UIComponent component, Object value) throws ConverterException {
if (value == null) {
throw new ConverterException("value not specified");
}
if (IsoDate.class.equals(value)) {
IsoDate isoDate = (IsoDate) value;
if (isoDate.isDummy()) {
return WebConst.ISO_DATE_NONE;
} else {
//TODO User spezifische TimeZone auslesen
return isoDate.toString(pattern, TimeZone.getDefault().getID(), false);
}
} else if (IsoTime.class.equals(value)) {
IsoTime isoTime = (IsoTime) value;
if (isoTime.isDummy()) {
return WebConst.ISO_TIME_NONE;
} else {
//TODO User spezifische TimeZone auslesen
return isoTime.toString(pattern, TimeZone.getDefault().getID(), false);
}
} else if (IsoTimestamp.class.equals(value)) {
IsoTimestamp isoTimestamp = (IsoTimestamp) value;
if (isoTimestamp.isDummy()) {
return WebConst.ISO_TIMESTAMP_NONE;
} else {
//TODO User spezifische TimeZone auslesen
return isoTimestamp.toString(pattern, TimeZone.getDefault().getID(), false);
}
} else {
throw new ConverterException("value not convertible");
}
}
@Override
public Object saveState(FacesContext context) {
return new Object[]{type, pattern};
}
@Override
public void restoreState(FacesContext context, Object state) {
type = (Class) ((Object[]) state)[0];
pattern = (String) ((Object[]) state)[1];
}
@Override
public boolean isTransient() {
return transientValue;
}
@Override
public void setTransient(boolean transientValue) {
this.transientValue = transientValue;
}
}
在以下视图中,我将Converter
用作<mh:IsoDateTimeConverter>
:
And I use the Converter
as <mh:IsoDateTimeConverter>
in the following view:
<p:dataTable value="#{imports.list}" var="item">
<p:column>
<h:outputText value="#{item.balanceDate}" immediate="true">
<mh:IsoDateTimeConverter type="#{webConst.ISO_DATE_CLASS}" pattern="#{webConst.ISO_DATE_FORMAT}"/>
</h:outputText>
</p:column>
</p:dataTable>
问题是,当我第一次打开该视图时,所有属性仅在我的Converter
类中设置一次,然后数据表根据初始属性呈现并转换值.
The problem is, when I first open this view, all properties are set in my Converter
class only once and then the datatable renders and converts the values based on initial properties.
我希望这些属性是按行设置的.我该如何实现?
I expected that the properties are set on a per-row basis. How can I achieve this?
推荐答案
至此,您希望每次呈现数据表行时都设置转换器的属性.确实不是这样.构建视图时,JSF将仅为每个组件创建一个转换器实例,而不是每次渲染该行时都将创建/重置转换器.
To the point, you expected that the converter's properties are set every time a datatable row is rendered. This is indeed not true. JSF will create only one converter instance per component when the view is to be built, it will not create/reset the converter each time the row is rendered.
有几种方法可以使其正常工作.
There are several ways to get it to work.
-
将动态属性作为组件的
<f:attribute>
传递,并让Converter
对其进行拦截.您可以在此处找到示例:在数据表中带有时区的JSF convertDateTime .然后可以用作
Pass the dynamic attributes as
<f:attribute>
of the component and let theConverter
intercept on that. You can find an example here: JSF convertDateTime with timezone in datatable. This can then be used as
<h:outputText value="#{item.balanceDate}">
<f:converter converterId="isoDateTimeConverter" />
<f:attribute name="pattern" value="#{item.pattern}" />
</h:outputText>
Use an EL function instead of a Converter
. You can find an example here: Facelets and JSTL (Converting a Date to a String for use in a field). This can then be used as
<h:outputText value="#{mh:convertIsoDate(item.balanceDate, item.pattern)}" />
将转换器和数据表的DataModel
绑定为同一托管Bean的属性.这样,您将能够在返回行之前根据行数据设置转换器的属性.这是一个基于标准JSF组件和标准DateTimeConverter
的基本启动示例(在PrimeFaces组件和您的自定义转换器上应同样有效):
Bind the converter and datatable's DataModel
as a property of the same managed bean. This way you will be able to set the converter's properties based on the row data before returning it. Here's a basic kickoff example based on standard JSF components and standard DateTimeConverter
(it should work equally good on PrimeFaces components and with your custom converter):
<h:dataTable value="#{bean.model}" var="item">
<h:column>
<h:outputText value="#{item.date}" converter="#{bean.converter}" />
</h:column>
</h:dataTable>
使用
@ManagedBean
@ViewScoped
public class Bean implements Serializable {
private List<Item> items;
private DataModel<Item> model;
private DateTimeConverter converter;
@PostConstruct
public void init() {
items = Arrays.asList(
new Item(new Date(), "dd-MM-yyyy"),
new Item(new Date(), "yyyy-MM-dd"),
new Item(new Date(), "MM/dd/yyyy"));
model = new ListDataModel<Item>(items);
converter = new DateTimeConverter();
}
public DataModel<Item> getModel() {
return model;
}
public Converter getConverter() {
converter.setPattern(model.getRowData().getPattern());
return converter;
}
}
(Item
类只是具有两个属性Date date
和String pattern
的bean)
(the Item
class is just a bean with two properties Date date
and String pattern
)
这导致
2011年9月23日
2011-09-23
2011年9月23日
23-09-2011
2011-09-23
09/23/2011
改为使用 OmniFaces <o:converter>
.它支持属性中EL的渲染时间评估.另请参见 <o:converter>
展示示例.
Use OmniFaces <o:converter>
instead. It supports render time evaluation of EL in the attributes. See also the <o:converter>
showcase example.
<h:outputText value="#{item.balanceDate}">
<o:converter converterId="isoDateTimeConverter" pattern="#{item.pattern}" />
</h:outputText>
这篇关于如何为h:dataTable/ui:repeat的每一行/项目设置转换器属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!