Jsf p:selectOneMenu不';t通过列表上的p:列呈现自定义内容<;字符串>;
我正在尝试使用Primefaces 5.2 SelectOne菜单来显示图像及其文件名。这就是我的xhtml当前的样子:Jsf p:selectOneMenu不';t通过列表上的p:列呈现自定义内容<;字符串>;,jsf,jsf-2,primefaces,selectonemenu,Jsf,Jsf 2,Primefaces,Selectonemenu,我正在尝试使用Primefaces 5.2 SelectOne菜单来显示图像及其文件名。这就是我的xhtml当前的样子: <h:form> <h:panelGrid id="createPanelGrid" columns="2"> <p:outputLabel value="Service Logo:" /> <p:selectOneMenu value="#{imageBean.selectedImage}" var="l">
<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>
然而,这些图片并没有呈现在网页上,只有文件名(我会发布一个截图,但我没有足够的声誉)。我没有得到两列(首先是图像,然后是文件名),我只得到文件名本身
当我将文件名字符串包装到POJO中并使用转换器时,它可以工作,但对于字符串就不行了
如何使其仅用于字符串?原因是Primefaces库在
selectOneMenu
组件的var
属性中指定了一个bean,但您提供的字符串对象不是bean。因此,库根本不渲染任何列覆盖。在var
属性中需要一个bean(包装器),在Converter
属性中需要相应的转换器。原因是Primefaces库在selectOneMenu
组件的var
属性中指定了一个bean,但您给出的字符串对象不是bean。因此,库根本不渲染任何列覆盖。在var
属性中需要一个bean(包装器),在Converter
属性中需要相应的转换器。这个笨拙的行为由(行号匹配5.2)确认:
因此,如果项目值是String
的实例,则通过
的自定义内容将被完全忽略。这确实没有任何意义。直观的预期是,自定义内容通过var
属性和/或
子项的存在进行切换。你最好向PrimeFaces的人报告一个问题来解释/改进这一点
除了提供非字符串
类型的项值之外,解决方法是使用自定义呈现程序覆盖SelectOneMenuRender
,该呈现程序将字符串
包装在另一个对象中,而该对象恰好在其toString()
中返回完全相同的值,例如StringBuilder
。这样,渲染器将被愚弄,因为这些值不是String
的实例。很高兴他们没有检查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);
}
}
这种尴尬的行为通过(行号匹配5.2)得到证实: 因此,如果项目值是
String
的实例,则通过
的自定义内容将被完全忽略。这确实没有任何意义。直观的预期是,自定义内容通过var
属性和/或
子项的存在进行切换。你最好向PrimeFaces的人报告一个问题来解释/改进这一点
除了提供非字符串
类型的项值之外,解决方法是使用自定义呈现程序覆盖SelectOneMenuRender
,该呈现程序将字符串
包装在另一个对象中,而该对象恰好在其toString()
中返回完全相同的值,例如StringBuilder
。这样,渲染器将被愚弄,因为这些值不是String
的实例。很高兴他们没有检查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);
}
}
日志中没有404-当我在文件名字符串周围使用包装器类时,同样的URL也可以工作。如果我在日志中找到了可以解释的线索,我就不会发布了。对不起,我不是说日志中没有线索,只是我找不到任何线索。你能给我一个提示我在找什么(除了404,我查过了)?另外,让我感到困惑的是,在服务器端更改内容(添加包装器类)可以让它工作。不,所需的元素最终不会出现在HTML输出中,而是被忽略了。相反,我只得到文本(文件名)。如果我使用包装器类,我就可以毫无问题地得到标签。日志中没有404——当我在文件名字符串周围使用包装器类时,同样的URL也可以工作。如果我在日志中找到了可以解释的线索,我就不会发布了。对不起,我不是说日志中没有线索,只是我找不到任何线索。你能给我一个提示我在找什么(除了404,我查过了)?另外,让我感到困惑的是,在服务器端更改内容(添加包装器类)可以让它工作。不,所需的元素最终不会出现在HTML输出中,而是被忽略了。相反,我只得到文本(文件名)。如果我使用包装器类,我就可以毫无问题地得到标签。是的,这是对我有效的解决方法-我只是希望有一种更简单的方法…这就是问题所在,没有解决方法,因为没有任何解决方法。这是将图像放入Primefaces SelectOne菜单的方法。如果我的回答澄清了你的问题,请接受我的回答。要将答案标记为已接受,请单击答案旁边的复选标记,将其从空心切换为绿色。谢谢。所以字符串不是POJO?我是说bean,而不是POJO。但是它与字符串关联,而不是与对象关联,所以如果我想将对象传递给bean,我该怎么做?是的,这是对我有效的解决方法-我只是希望有一种更简单的方法…这就是问题所在,没有变通办法,因为没有变通办法。这是将图像放入Primefaces SelectOne菜单的方法。如果我的回答澄清了你的问题,请接受我的回答。要将答案标记为已接受,请单击答案旁边的复选标记,将其从空心切换为绿色。谢谢。所以字符串不是POJO?我指的是bean,而不是POJO。但它与字符串关联,而不是与对象关联,所以如果我想将对象传递给bean,我该怎么做?哇。。。非常感谢!我从来没有想过这种行为是故意的。。。再次感谢您提供了良好的解决方案!如果您有像
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 }
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);
}
}
<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>