在 <p:megaMenu> 的 <p:menuitem> 中实现 <o:graphicImage> 而不是图标
Implement <o:graphicImage> instead of icon in <p:menuitem> of <p:megaMenu>
好的,标题有点混乱,但我不知道如何用一句话表达我的问题。
所以这是交易:
我需要以某种方式在 MenuItem 组件中实现来自 Primefaces 的 graphicImage 组件(或者更好的是 Omnifaces,因为我从数据库加载图像并且我已经在应用程序中使用了 o:graphicImage),以便在以编程方式使用创建的 MegaMenu 组件中显示它在辅助 bean 中创建的 DefaultMenuModel。另外(正如我上面提到的),图像是从数据库加载的,所以我想通过 css 加载这些图像(图标)的解决方案不适用,因为图像是动态的。
我尝试了很多方法,但(不用说)不幸的是,我惨遭失败:-( 。我没有编写全栈 Primefaces 自定义组件的任何经验,所以我尝试使用一些基本的自定义渲染器来制作 MegaMenu 组件。例如,我尝试使用来自 o:graphicImage 组件(encodeBegin 和 encodeEnd)的代码,并在我的 CustomMegaMenuRenderer(它扩展了 MegaMenuRenderer)中以覆盖的方法 encodeMenuItemContent 实现它。我使用了一些技巧来传递 EL 表达式(如#{imageStreamer.getImage(23)},其中 23 是实际图像 ID)将此字符串作为模型中 MenuItem 组件的 'icon' 字段的值传递。然后,在覆盖的 encodeMenuItemContent 中,我检查它是否实际上是 el(而不是图标名称) 我做这样的事情:
writer.startElement("img", null);
writer.writeURIAttribute("src", getSrc(context, expresion), "value");
writeAttributes(writer, this, GraphicImage.ATTRIBUTE_NAMES);
writer.endElement("img");
其中 getSrc(context, expression) 的实现方式如下:
private String getSrc(FacesContext context, String expression) throws IOException {
Resource resource;
ExpressionFactory ef = context.getApplication().getExpressionFactory();
ValueExpression dynExpression = ef.createValueExpression(context.getELContext(), expression, Object.class);
resource = GraphicResource.create(context, dynExpression, null);
return context.getExternalContext().encodeResourceURL(resource.getRequestPath());
}
但不幸的是,getSrc(context, expression) 无法像在通常装箱的 o:graphicImage 组件中那样 return 字符串内容。
我还尝试了一些其他方法,例如在我的渲染中以编程方式实例化 graphicImage 组件(来自 Primefaces 或 Omnifaces),然后在 object 上调用 encodeAll 方法,但这也失败了...
GraphicImage gi = (GraphicImage) application.createComponent(GraphicImage.COMPONENT_TYPE);
gi.getAttributes().put("value", expression);
gi.encodeAll(context);
所以我得出结论,我在那里遗漏了一些非常重要的东西。我试图在 SO 和 google 上找到类似的东西,但未能成功。所以,这里是我真正的问题(假设我的方法不好):
- 是否可以实例化每个事件 primefaces/omnifaces
自定义渲染器中的组件并使其正常工作
正常工作(因此它会按预期呈现)?我猜这
将是使我的渲染器按预期工作的最简单方法...
- 我应该继续使用这种 "custom renderer" 方法还是
在这种情况下没用?
- 我是否必须在中制作自定义 MenuModel、MenuItem 或 MegaMenu class
为了创建上面解释的这个功能?
- 最后,理论上最简单的方法是什么?
"the best" 实现这一目标的方法是什么(因此它与
primefaces组件设计,这个"should be"究竟是怎么做到的)?
还要提一下(但我想它超出了范围),我使用 JSF MOJARRA 2.2.9、Primefaces 5.1、Omnifaces 2.0 和 Weld on Tomcat 8.
提前致谢。
据我了解,您尝试使用类似的东西:
<p:menuitem ... icon="#{imageStreamer.getImage(23)}" />
这确实不行。当渲染器获得它时,它会立即被评估。这也不是 <o:graphicImage>
的工作方式。它将评估推迟到浏览器实际需要请求图像的那一刻。
最好的办法是传递图像标识符:
<p:menuitem ... icon="23" />
(可以安全地作为 icon="#{bean.iconId}"
之类的表达式)
然后你可以渲染如下:
@Override
protected void encodeMenuItemContent(FacesContext context, AbstractMenu menu, MenuItem menuitem) throws IOException {
ResponseWriter writer = context.getResponseWriter();
String imageId = menuitem.getIcon();
Object value = menuitem.getValue();
if (imageId != null) {
ValueExpression expression = Components.createValueExpression("#{imageStreamer.getImage(" + imageId + ")}", Object.class);
GraphicResource resource = GraphicResource.create(context, expression, null);
String src = context.getExternalContext().encodeResourceURL(resource.getRequestPath());
writer.startElement("img", null);
writer.writeURIAttribute("src", src, null);
writer.endElement("img");
}
// ...
}
(你非常接近,只是不幸的是你没有展示你是如何创建 expression
以及它究竟是如何失败的,这样才能查明确切的原因)
好的,标题有点混乱,但我不知道如何用一句话表达我的问题。
所以这是交易: 我需要以某种方式在 MenuItem 组件中实现来自 Primefaces 的 graphicImage 组件(或者更好的是 Omnifaces,因为我从数据库加载图像并且我已经在应用程序中使用了 o:graphicImage),以便在以编程方式使用创建的 MegaMenu 组件中显示它在辅助 bean 中创建的 DefaultMenuModel。另外(正如我上面提到的),图像是从数据库加载的,所以我想通过 css 加载这些图像(图标)的解决方案不适用,因为图像是动态的。
我尝试了很多方法,但(不用说)不幸的是,我惨遭失败:-( 。我没有编写全栈 Primefaces 自定义组件的任何经验,所以我尝试使用一些基本的自定义渲染器来制作 MegaMenu 组件。例如,我尝试使用来自 o:graphicImage 组件(encodeBegin 和 encodeEnd)的代码,并在我的 CustomMegaMenuRenderer(它扩展了 MegaMenuRenderer)中以覆盖的方法 encodeMenuItemContent 实现它。我使用了一些技巧来传递 EL 表达式(如#{imageStreamer.getImage(23)},其中 23 是实际图像 ID)将此字符串作为模型中 MenuItem 组件的 'icon' 字段的值传递。然后,在覆盖的 encodeMenuItemContent 中,我检查它是否实际上是 el(而不是图标名称) 我做这样的事情:
writer.startElement("img", null);
writer.writeURIAttribute("src", getSrc(context, expresion), "value");
writeAttributes(writer, this, GraphicImage.ATTRIBUTE_NAMES);
writer.endElement("img");
其中 getSrc(context, expression) 的实现方式如下:
private String getSrc(FacesContext context, String expression) throws IOException {
Resource resource;
ExpressionFactory ef = context.getApplication().getExpressionFactory();
ValueExpression dynExpression = ef.createValueExpression(context.getELContext(), expression, Object.class);
resource = GraphicResource.create(context, dynExpression, null);
return context.getExternalContext().encodeResourceURL(resource.getRequestPath());
}
但不幸的是,getSrc(context, expression) 无法像在通常装箱的 o:graphicImage 组件中那样 return 字符串内容。
我还尝试了一些其他方法,例如在我的渲染中以编程方式实例化 graphicImage 组件(来自 Primefaces 或 Omnifaces),然后在 object 上调用 encodeAll 方法,但这也失败了...
GraphicImage gi = (GraphicImage) application.createComponent(GraphicImage.COMPONENT_TYPE);
gi.getAttributes().put("value", expression);
gi.encodeAll(context);
所以我得出结论,我在那里遗漏了一些非常重要的东西。我试图在 SO 和 google 上找到类似的东西,但未能成功。所以,这里是我真正的问题(假设我的方法不好):
- 是否可以实例化每个事件 primefaces/omnifaces 自定义渲染器中的组件并使其正常工作 正常工作(因此它会按预期呈现)?我猜这 将是使我的渲染器按预期工作的最简单方法...
- 我应该继续使用这种 "custom renderer" 方法还是 在这种情况下没用?
- 我是否必须在中制作自定义 MenuModel、MenuItem 或 MegaMenu class 为了创建上面解释的这个功能?
- 最后,理论上最简单的方法是什么? "the best" 实现这一目标的方法是什么(因此它与 primefaces组件设计,这个"should be"究竟是怎么做到的)?
还要提一下(但我想它超出了范围),我使用 JSF MOJARRA 2.2.9、Primefaces 5.1、Omnifaces 2.0 和 Weld on Tomcat 8.
提前致谢。
据我了解,您尝试使用类似的东西:
<p:menuitem ... icon="#{imageStreamer.getImage(23)}" />
这确实不行。当渲染器获得它时,它会立即被评估。这也不是 <o:graphicImage>
的工作方式。它将评估推迟到浏览器实际需要请求图像的那一刻。
最好的办法是传递图像标识符:
<p:menuitem ... icon="23" />
(可以安全地作为 icon="#{bean.iconId}"
之类的表达式)
然后你可以渲染如下:
@Override
protected void encodeMenuItemContent(FacesContext context, AbstractMenu menu, MenuItem menuitem) throws IOException {
ResponseWriter writer = context.getResponseWriter();
String imageId = menuitem.getIcon();
Object value = menuitem.getValue();
if (imageId != null) {
ValueExpression expression = Components.createValueExpression("#{imageStreamer.getImage(" + imageId + ")}", Object.class);
GraphicResource resource = GraphicResource.create(context, expression, null);
String src = context.getExternalContext().encodeResourceURL(resource.getRequestPath());
writer.startElement("img", null);
writer.writeURIAttribute("src", src, null);
writer.endElement("img");
}
// ...
}
(你非常接近,只是不幸的是你没有展示你是如何创建 expression
以及它究竟是如何失败的,这样才能查明确切的原因)