首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >基于Primefaces的<p:diagram>创建自定义组件

基于Primefaces的<p:diagram>创建自定义组件
EN

Stack Overflow用户
提问于 2018-07-26 15:35:30
回答 1查看 2K关注 0票数 4

多年来,我一直在隐藏这个帮助社区,但从未发布过,因为我通常会在询问之前找到我需要的。

我读过这些文章:

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浏览器能够正确地解释<mark>, <strong>data标记,用于Element of <p:diagram>Element属性。我还没有找到一个没有实现我自己的组件的解决方案。

了解一下JSF的<h:outputText>如何给出正确解释escape标记的选项后,我考虑将这个标记和它的行为添加到<p:diagram>组件中,并创建自己的组件(以后可能还需要添加进一步的定制)。

下面是我的标签库:

代码语言:javascript
复制
<?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>

这是我的组成部分:

代码语言:javascript
复制
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);
}
}

这是我的定制渲染器:

代码语言:javascript
复制
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");
}
}

考虑到我在Renderer上使用了注释,我没有修改faces-config.xml。

然后,我将视图中的新组件调用为:

代码语言:javascript
复制
<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"/>

myBean是我的后盾,它包含我的DefaultDiagramModel (primefaces对象)。

当我显示我的页面时,我有以下错误(我随意裁剪它,如果需要,我可以给出完整的堆栈跟踪):

代码语言:javascript
复制
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)
    [...]

这个错误意味着JSF无法实例化myComponent.component.type类型的组件(这将是Diagram.COMPONENT_FAMILY,又名org.primefaces.component)。

最后,我的问题是:知道我做错了什么吗?我忘了什么吗?是否有人必须创建基于Primefaces图的自定义组件?

谢谢你们的帮助:)

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-07-26 15:42:03

通常,我会评论而不回答,但是我看到了您的代码中的一些问题。

在我覆盖Datatable的代码中,我必须将其添加到faces-config.xml中,以便将其捡起。我本以为您的@FacesComponent注释会做到这一点。

代码语言:javascript
复制
<!-- 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属性的"setter“只是一个getter。您需要这两种方法来设置值。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51542648

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档