JSF 条件转换器
JSF conditional converter
我创建了一个非常通用的 jsf 复合组件,它从通用行数据中呈现一个 primefaces dataTable。
对于应该呈现的每一行,我有一个名为 ColumnDescription 的 pojo,其中包含 header 名称和用于获取数据的行数据索引。
这工作正常,但现在我有允许在列上设置可选转换器的请求。
所以我用 converterId 扩展了 ColumnDescription。
问题是,如果 ColumnDescription 中的 converterId 不为空,我只需要将转换器附加到。
第一个想法:
<h:outputText value="#{row[column.rowBeanProperty]}">
<c:if test="#{column.hasConverter}">
<f:converter converterId="#{column.converterId}" />
</c:if>
这没有用。 if 标签中的测试甚至不会被评估。
我认为这是因为将评估 jsp 标签的不同阶段。
第二个想法
使用渲染的属性作为条件
<h:outputText value="#{row[column.rowBeanProperty]}">
<ui:fragment rendered="#{column.hasConverter}">
<f:converter converterId="#{column.converterId}" />
</ui:fragment>
这不起作用,因为转换器需要附加到可编辑值组件
TagException: /components/dataReport.xhtml @38,80 <f:converter> Parent not an instance of ValueHolder: com.sun.faces.facelets.tag.ui.ComponentRef@35b683c2
是否有机会有条件地添加转换器?
提前致谢
塞巴斯蒂安
您可以做的是编写自己的转换器。看How create a custom converter in JSF 2?. If you know you can get a converter by calling context.getApplication().createConverter(converterId)
,很简单:
@FacesConverter("optionalConverter")
public class OptionalConverter implements Converter {
private String converterId;
private boolean disabled;
@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
return disabled
? value
: context.getApplication().createConverter(converterId).getAsObject(context, component, value);
}
@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
if (value == null) {
return null;
}
return disabled
? value.toString()
: context.getApplication().createConverter(converterId).getAsString(context, component, value);
}
// Getters and setters
}
然后为该转换器创建一个标签。参见 How to create a custom Facelets tag?。因此,在 /WEB-INF/
:
中创建一个名为 my.taglib.xml
的文件
<?xml version="1.0" encoding="UTF-8"?>
<facelet-taglib xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facelettaglibrary_2_0.xsd"
version="2.0">
<namespace>http://my.com/jsf/facelets</namespace>
<tag>
<tag-name>optionalConverter</tag-name>
<converter>
<converter-id>optionalConverter</converter-id>
</converter>
<attribute>
<name>converterId</name>
<required>true</required>
<type>java.lang.String</type>
</attribute>
<attribute>
<name>disabled</name>
<required>false</required>
<type>boolean</type>
</attribute>
</tag>
</facelet-taglib>
并将其添加到 web.xml
:
<context-param>
<param-name>javax.faces.FACELETS_LIBRARIES</param-name>
<param-value>/WEB-INF/my.taglib.xml</param-value>
</context-param>
测试:
Enabled:
<h:outputText value="1234">
<my:optionalConverter converterId="javax.faces.Number" />
</h:outputText>
Disabled:
<h:outputText value="1234">
<my:optionalConverter converterId="javax.faces.Number" disabled="true" />
</h:outputText>
输出:"Enabled: 1,234 Disabled: 1234".
我创建了一个非常通用的 jsf 复合组件,它从通用行数据中呈现一个 primefaces dataTable。
对于应该呈现的每一行,我有一个名为 ColumnDescription 的 pojo,其中包含 header 名称和用于获取数据的行数据索引。
这工作正常,但现在我有允许在列上设置可选转换器的请求。
所以我用 converterId 扩展了 ColumnDescription。 问题是,如果 ColumnDescription 中的 converterId 不为空,我只需要将转换器附加到。
第一个想法:
<h:outputText value="#{row[column.rowBeanProperty]}">
<c:if test="#{column.hasConverter}">
<f:converter converterId="#{column.converterId}" />
</c:if>
这没有用。 if 标签中的测试甚至不会被评估。 我认为这是因为将评估 jsp 标签的不同阶段。
第二个想法 使用渲染的属性作为条件
<h:outputText value="#{row[column.rowBeanProperty]}">
<ui:fragment rendered="#{column.hasConverter}">
<f:converter converterId="#{column.converterId}" />
</ui:fragment>
这不起作用,因为转换器需要附加到可编辑值组件
TagException: /components/dataReport.xhtml @38,80 <f:converter> Parent not an instance of ValueHolder: com.sun.faces.facelets.tag.ui.ComponentRef@35b683c2
是否有机会有条件地添加转换器?
提前致谢 塞巴斯蒂安
您可以做的是编写自己的转换器。看How create a custom converter in JSF 2?. If you know you can get a converter by calling context.getApplication().createConverter(converterId)
,很简单:
@FacesConverter("optionalConverter")
public class OptionalConverter implements Converter {
private String converterId;
private boolean disabled;
@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
return disabled
? value
: context.getApplication().createConverter(converterId).getAsObject(context, component, value);
}
@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
if (value == null) {
return null;
}
return disabled
? value.toString()
: context.getApplication().createConverter(converterId).getAsString(context, component, value);
}
// Getters and setters
}
然后为该转换器创建一个标签。参见 How to create a custom Facelets tag?。因此,在 /WEB-INF/
:
my.taglib.xml
的文件
<?xml version="1.0" encoding="UTF-8"?>
<facelet-taglib xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facelettaglibrary_2_0.xsd"
version="2.0">
<namespace>http://my.com/jsf/facelets</namespace>
<tag>
<tag-name>optionalConverter</tag-name>
<converter>
<converter-id>optionalConverter</converter-id>
</converter>
<attribute>
<name>converterId</name>
<required>true</required>
<type>java.lang.String</type>
</attribute>
<attribute>
<name>disabled</name>
<required>false</required>
<type>boolean</type>
</attribute>
</tag>
</facelet-taglib>
并将其添加到 web.xml
:
<context-param>
<param-name>javax.faces.FACELETS_LIBRARIES</param-name>
<param-value>/WEB-INF/my.taglib.xml</param-value>
</context-param>
测试:
Enabled:
<h:outputText value="1234">
<my:optionalConverter converterId="javax.faces.Number" />
</h:outputText>
Disabled:
<h:outputText value="1234">
<my:optionalConverter converterId="javax.faces.Number" disabled="true" />
</h:outputText>
输出:"Enabled: 1,234 Disabled: 1234".