本文介绍了p:selectOneMenu 不会通过 List<String> 上的 p:column 呈现自定义内容.的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 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 类型的项目值外,解决方法是使用包装StringSelectOneMenuRenderercode> 在另一个对象中,该对象恰好在其 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 呈现自定义内容.的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-25 13:19