问题描述
我正在尝试使用 Primefaces 5.2 selectOneMenu 来显示图像及其文件名.这是我的 xhtml 目前的样子:
I'm trying to get a Primefaces 5.2 selectOneMenu to display images along with their filenames. This is what my xhtml currently looks like:
<h:form>
<h:panelGrid id="createPanelGrid" columns="2">
<p:outputLabel value="Service Logo:" />
<p:selectOneMenu value="#{imageBean.selectedImage}" var="l">
<f:selectItem itemLabel="Select a logo" itemValue="" />
<f:selectItems value="#{imageBean.imageList}" var="logo" itemLabel="#{logo}" itemValue="#{logo}" />
<p:column>
<p:graphicImage value="#{imageBean.imageFolder}/#{l}" style="max-width:50px;max-height:50px;" />
</p:column>
<p:column>#{l}</p:column>
</p:selectOneMenu>
</h:panelGrid>
ManagedBean (imageBean) 有
The ManagedBean (imageBean) has
public List<String> getImageList () {
List<String> imageList = new ArrayList<String>();
File[] files = absoluteImageFolder.listFiles();
for (File file : files) {
imageList.add(file.getName());
}
return imageList;
}
和
private String selectedImage;
public String getSelectedImage() {
return selectedImage;
}
public void setSelectedImage(String selectedImage) {
this.selectedImage = selectedImage;
}
但是,图像并未呈现在网页上,只是文件名(我会发布屏幕截图,但我没有足够的声誉).我没有得到两列(首先是图像,然后是文件名),我只得到了文件名本身.
However, the images are not rendered on the webpage, just the filenames (I'd post a screenshot but I don't have enough reputation). I don't get two columns (first the image, then the filename), I just get the filename itself.
当我将文件名字符串包装成 POJO 并使用转换器时,它可以工作 - 但仅使用字符串就不行.
When I wrap the filename Strings into a POJO and use a converter it works - but just with Strings it doesn't.
我怎样才能让它只与字符串一起工作?
How can I get this to work with just Strings?
推荐答案
SelectOneMenuRenderer
源代码(行号匹配 5.2):
This awkward behavior is confirmed by SelectOneMenuRenderer
source code (line numbers match 5.2):
260 if(itemValue instanceof String) {
261 writer.startElement("td", null);
262 writer.writeAttribute("colspan", columns.size(), null);
263 writer.writeText(selectItem.getLabel(), null);
264 writer.endElement("td");
265 }
266 else {
267 for(Column column : columns) {
268 writer.startElement("td", null);
269 renderChildren(context, column);
270 writer.endElement("td");
271 }
272 }
因此,如果 item 值是 String
的实例,则通过 的自定义内容将被完全忽略.这确实没有任何意义.直观的期望是自定义内容通过
var
属性和/或 子项的存在来切换.您最好向 PrimeFaces 人员报告问题以解释/改进这一点.
So, if the item value is an instance of String
, custom content via <p:column>
is totally ignored. This does indeed not make any sense. The intuitive expectation is that the custom content is toggled by presence of var
attribute and/or <p:column>
children. You'd best report an issue to PrimeFaces guys to explain/improve this.
除了提供非String
类型的项目值外,解决方法是使用包装String的自定义渲染器覆盖
SelectOneMenuRenderer
code> 在另一个对象中,该对象恰好在其 toString()
中返回完全相同的值,例如 StringBuilder
.这样渲染器就会被愚弄,认为这些值不是 String
的实例.很高兴他们没有检查 instanceof CharSequence
.
The work around, apart from providing non-String
-typed item values, is to override the SelectOneMenuRenderer
with a custom renderer which wraps the String
in another object which happens to return exactly the same value in its toString()
, such as StringBuilder
. This way the renderer will be fooled that the values aren't an instance of String
. Glad they didn't check for instanceof CharSequence
.
public class YourSelectOneMenuRenderer extends SelectOneMenuRenderer {
@Override
protected void encodeOptionsAsTable(FacesContext context, SelectOneMenu menu, List<SelectItem> selectItems) throws IOException {
List<SelectItem> wrappedSelectItems = new ArrayList<>();
for (SelectItem selectItem : selectItems) {
Object value = selectItem.getValue();
if (value instanceof String) {
value = new StringBuilder((String) value);
}
wrappedSelectItems.add(new SelectItem(value, selectItem.getLabel()));
}
super.encodeOptionsAsTable(context, menu, wrappedSelectItems);
}
}
为了让它运行,在faces-config.xml
中注册如下:
In order to get it to run, register it as below in faces-config.xml
:
<render-kit>
<renderer>
<component-family>org.primefaces.component</component-family>
<renderer-type>org.primefaces.component.SelectOneMenuRenderer</renderer-type>
<renderer-class>com.example.YourSelectOneMenuRenderer</renderer-class>
</renderer>
</render-kit>
这篇关于p:selectOneMenu 不会通过 List<String> 上的 p:column 呈现自定义内容.的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!