根据Primefaces的<p:diagram>

时间:2018-07-26 15:35:31

标签: jsf primefaces custom-controls



我已经在这个帮助社区中潜伏了很多年了,但是从未发布过,因为我通常会在问之前找到我需要的东西。
我已经阅读了那些文章:

How to render a composite component using a custom renderer?
What is the relationship between component family, component type and renderer type?

,但是我仍然试图基于Primefaces <p:diagram>创建自己的组件。

该组件本身几乎可以满足我的需求,但是我需要Web浏览器能够正确解释{{1}的<mark>, <strong>的{​​{1}}属性的HTML标签,例如data }}。我尚未找到没有实现自己的组件的解决方案。

有点了解JSF的Element如何(通过<p:diagram>标签)提供正确解释HTML标签的选项,我考虑过将此标签及其行为添加到<h:outputText>组件中,并制作自己的组件(稍后可能还要添加其他自定义)。

这是我的taglib:

escape


这是我的组件:

<p:diagram>


这是我的自定义渲染器:

<?xml version="1.0" encoding="UTF-8"?>
<facelet-taglib xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facelettaglibrary_2_0.xsd" version="2.0">
<namespace>http://myNamespace</namespace>
<tag>
    <tag-name>logigramme</tag-name>
    <description><![CDATA[]]></description>
    <component>
        <component-type>myComponent.component.type</component-type>
        <renderer-type>myComponentRenderer.renderer.type</renderer-type>
    </component>
    <attribute>
        <description><![CDATA[Unique identifier of the component in a namingContainer.]]></description>
        <name>id</name>
        <required>false</required>
        <type>java.lang.String</type>
    </attribute>
    <attribute>
        <description><![CDATA[Boolean value to specify the rendering of the component, when set to false component will not be rendered.]]></description>
        <name>rendered</name>
        <required>false</required>
        <type>java.lang.Boolean</type>
    </attribute>
    <attribute>
        <description><![CDATA[An el expression referring to a server side UIComponent instance in a backing bean.]]></description>
        <name>binding</name>
        <required>false</required>
        <type>javax.faces.component.UIComponent</type>
    </attribute>
    <attribute>
        <description><![CDATA[Value of the component.]]></description>
        <name>value</name>
        <required>false</required>
        <type>java.lang.Object</type>
    </attribute>
    <attribute>
        <description><![CDATA[An el expression or a literal text that defines a converter for the component. When it's an EL expression, it's resolved to a converter instance. 
In case it's a static text, it must refer to a converter id.]]></description>
        <name>converter</name>
        <required>false</required>
        <type>java.faces.convert.Converter</type>
    </attribute>
    <attribute>
        <description><![CDATA[Name of the client side widget.]]></description>
        <name>widgetVar</name>
        <required>false</required>
        <type>java.lang.String</type>
    </attribute>
    <attribute>
        <description><![CDATA[Name of the iterator variable used to refer each data.]]></description>
        <name>var</name>
        <required>false</required>
        <type>java.lang.String</type>
    </attribute>
    <attribute>
        <description><![CDATA[Inline style of the component.]]></description>
        <name>style</name>
        <required>false</required>
        <type>java.lang.String</type>
    </attribute>
    <attribute>
        <description><![CDATA[Style class of the component.]]></description>
        <name>styleClass</name>
        <required>false</required>
        <type>java.lang.String</type>
    </attribute>
    <attribute>
        <description><![CDATA[Flag indicating that characters that are sensitive in HTML and XML markup must be escaped. This flag is set to "true" by default.]]></description>
        <name>escape</name>
        <required>false</required>
        <type>java.lang.Boolean</type>
    </attribute>
</tag>

考虑到我在渲染器上使用了注释,所以我没有修改faces-config.xml。

然后我用:

调用视图中的新组件。
package myPackage;

import javax.faces.component.FacesComponent;

import org.primefaces.component.diagram.Diagram;

@FacesComponent("logigramme")
public class Logigramme extends Diagram {

public static final String COMPONENT_TYPE = "myComponent.component.type";

public static final String DEFAULT_RENDERER = "myComponentRenderer.renderer.type";

protected enum PropertyKeys {
    widgetVar, var, style, styleClass, escape;
    String toString;

    PropertyKeys(String toString) {
        this.toString = toString;
    }

    PropertyKeys() {
    }

    public String toString() {
        return ((this.toString != null) ? this.toString : super.toString());
    }
}

public Logigramme() {
    setRendererType(DEFAULT_RENDERER);
}

public String getEscape() {
    return (String) getStateHelper().eval(PropertyKeys.escape, null);
}
}

其中package myPackage; import java.io.IOException; import java.util.List; import java.util.Map; import javax.faces.component.UIComponent; import javax.faces.context.FacesContext; import javax.faces.context.ResponseWriter; import javax.faces.render.FacesRenderer; import org.primefaces.component.diagram.Diagram; import org.primefaces.component.diagram.DiagramRenderer; import org.primefaces.model.diagram.Connection; import org.primefaces.model.diagram.DiagramModel; import org.primefaces.model.diagram.Element; import org.primefaces.model.diagram.connector.Connector; import org.primefaces.model.diagram.endpoint.EndPoint; import org.primefaces.model.diagram.overlay.Overlay; import org.primefaces.renderkit.CoreRenderer; import org.primefaces.util.SharedStringBuilder; import org.primefaces.util.WidgetBuilder; @FacesRenderer(componentFamily = Diagram.COMPONENT_FAMILY, rendererType=Logigramme.DEFAULT_RENDERER) public class LogigrammeRenderer extends DiagramRenderer { @Override public void decode(FacesContext context, UIComponent component) { Logigramme logigramme = (Logigramme) component; if (logigramme.isConnectRequest(context)) { decodeNewConnection(context, logigramme); } else if (logigramme.isDisconnectRequest(context)) { decodeDisconnection(context, logigramme); } else if (logigramme.isConnectionChangeRequest(context)) { decodeConnectionChange(context, logigramme); } decodeBehaviors(context, component); } [...] @Override public void encodeEnd(FacesContext context, UIComponent component) throws IOException { Logigramme logigramme = (Logigramme) component; encodeMarkup(context, logigramme); encodeScript(context, logigramme); } [...] protected void encodeMarkup(FacesContext context, Logigramme logigramme) throws IOException { ResponseWriter writer = context.getResponseWriter(); DiagramModel model = (DiagramModel) logigramme.getValue(); String clientId = logigramme.getClientId(context); String style = logigramme.getStyle(); String styleClass = logigramme.getStyleClass(); styleClass = (styleClass == null) ? Logigramme.CONTAINER_CLASS : Logigramme.CONTAINER_CLASS + " " + styleClass; UIComponent elementFacet = logigramme.getFacet("element"); Map<String, Object> requestMap = context.getExternalContext().getRequestMap(); String var = logigramme.getVar(); Boolean escape = Boolean.valueOf(logigramme.getEscape()); writer.startElement("div", logigramme); writer.writeAttribute("id", logigramme.getClientId(context), null); writer.writeAttribute("class", styleClass, null); if (style != null) { writer.writeAttribute("style", style, null); } if (model != null) { List<Element> elements = model.getElements(); if (elements != null && !elements.isEmpty()) { for (int i = 0; i < elements.size(); i++) { Element element = elements.get(i); String elementClass = element.getStyleClass(); elementClass = (elementClass == null) ? Logigramme.ELEMENT_CLASS : Logigramme.ELEMENT_CLASS + " " + elementClass; if (element.isDraggable()) { elementClass = elementClass + " " + Logigramme.DRAGGABLE_ELEMENT_CLASS; } Object data = element.getData(); String x = element.getX(); String y = element.getY(); String coords = "left:" + x + ";top:" + y; writer.startElement("div", null); writer.writeAttribute("id", clientId + "-" + element.getId(), null); writer.writeAttribute("class", elementClass, null); writer.writeAttribute("style", coords, null); if (elementFacet != null && var != null) { requestMap.put(var, data); elementFacet.encodeAll(context); } else if (data != null) { if (escape == null || escape) { writer.writeText(data, null); } else { writer.write(data.toString()); } } writer.endElement("div"); } } if (var != null) { requestMap.remove(var); } } writer.endElement("div"); } } 是包含我的DefaultDiagramModel(primefaces对象)的Backing bean。

当我显示我的页面时,出现以下错误(我可以随意裁剪,可以根据需要提供完整的堆栈跟踪信息):

<ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core" xmlns:p="http://primefaces.org/ui" xmlns:odc="http://myNamespace">

[...]

<odc:logigramme value="#{myBean.model}" styleClass="ui-widget-content" widgetVar="logigrammeWV" escape="false"/>

松散地翻译,该错误意味着JSF无法实例化类型为myBean(即INFOS: Facelet[/views/incident/listeIncidents.xhtml] was modified @ 11:06:19, flushing component applied @ 11:06:15 juil. 26, 2018 11:06:19 AM com.sun.faces.application.ApplicationImpl createComponentApplyAnnotations GRAVE: JSF1068 : Impossible d’instancier un composant dont le type est myComponent.component.type javax.faces.FacesException: Erreur d’expression : objet nommé «myComponent.component.type» non détecté at com.sun.faces.application.ApplicationImpl.createComponentApplyAnnotations(ApplicationImpl.java:1933) at com.sun.faces.application.ApplicationImpl.createComponent(ApplicationImpl.java:1168) at javax.faces.application.ApplicationWrapper.createComponent(ApplicationWrapper.java:637) [...] ,也称为myComponent.component.type)的Component

因此,最后,我的问题是:我对自己做错的任何想法吗?我忘记了什么吗?是否有人必须基于Primefaces的图表创建自定义组件?

感谢您的帮助:)

1 个答案:

答案 0 :(得分:1)

通常,我会发表评论而不是回答,但是我发现您的代码存在一些问题。

在我重写数据表的代码中,必须将其添加到我的faces-config.xml中才能将其拾取。我本以为您的@FacesComponent批注会做到这一点。

<!-- Extend PF Datatable component and rendering to fix filter map handling -->
<component>
    <component-type>org.primefaces.component.DataTable</component-type>
    <component-class>com.stuff.web.faces.MyDataTable</component-class>
</component>
<render-kit>
   <renderer>
       <component-family>org.primefaces.component</component-family>
       <renderer-type>org.primefaces.component.DataTableRenderer</renderer-type>
       <renderer-class>com.stuff.faces.MyDataTableRenderer</renderer-class>
   </renderer>
</render-kit>

第二,除非您的示例被截断,否则我不会看到您的Escape属性的“设置者”只是吸气剂。您将需要两者来设置值。