1

好的,标题有点混乱,但我不知道如何用一句话来解决我的问题。

所以这是交易:我需要在 MenuItem 组件中以某种方式从 Primefaces(或者更好的是 Omnifaces,因为我从数据库加载图像并且我已经在应用程序中使用 o:graphicImage)实现 graphicsImage 组件,以便在 MegaMenu 组件中显示它使用在支持 bean 中创建的 DefaultMenuModel 以编程方式创建。另外(正如我上面提到的),图像是从数据库加载的,所以我想通过 css 加载这些图像(图标)的解决方案不适用,因为图像是动态的。

我尝试了很多方法,但(不用说)不幸的是,我失败了:-(。我没有任何编写全栈 Primefaces 自定义组件的经验,所以我尝试了一些基本的 MegaMenu 组件自定义渲染器。例如,我试过使用来自 o:graphicImage 组件(encodeBegin 和 encodeEnd)的代码并在我的 CustomMegaMenuRenderer(它扩展了 MegaMenuRenderer)中的重写方法 encodeMenuItemContent 中实现它。我使用小技巧来传递 EL 表达式(如 #{imageStreamer.getImage(23)},其中23 是实际图像 ID)将此字符串作为模型中 MenuItem 组件的“图标”字段的值传递。然后,在覆盖的 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 组件中那样返回字符串内容。

我还尝试了其他一些方法,例如在渲染中以编程方式实例化graphicImage组件(来自Primefaces或Omnifaces),然后在对象上调用encodeAll方法,但这也失败了......

GraphicImage gi = (GraphicImage) application.createComponent(GraphicImage.COMPONENT_TYPE);
gi.getAttributes().put("value", expression);
gi.encodeAll(context);

所以我得出结论,我在那里错过了一些非常大的东西。我试图在 SO 和 google 上找到类似的东西,但未能成功。所以,这里是我真正的问题(假设我的方法很糟糕):

  1. 是否可以在自定义渲染器中实例化每个 primefaces/omnifaces 组件并使其像正常工作一样工作(所以它按预期呈现自己)?我想这将是让我的渲染器按需要工作的最简单方法......
  2. 我应该继续使用这种“自定义渲染器”方法还是在这种情况下没用?
  3. 我是否必须制作自定义 MenuModel、MenuItem 或 MegaMenu 类才能创建上述功能?
  4. 最后,什么是理论上最简单的实现方式,什么是实现这个的“最佳”方式(因此它与 primefaces 组件设计相一致,实际上“应该”如何完成)?

还要提一下(但我猜它超出了范围),我在 Tomcat 8 上使用 JSF MOJARRA 2.2.9、Primefaces 5.1、Omnifaces 2.0 和 Weld。

提前致谢。

4

1 回答 1

0

据我了解,您试图使用类似的东西:

<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的以及它是如何失败的,以便可以查明确切的原因)

于 2015-01-13T14:06:21.023 回答