JSF / primefaces eventing in diagram elements

允我心安 提交于 2021-02-08 06:15:07

问题


i need to access the data object of an org.primefaces.model.diagram.Element in a managedBean on click of this very element. I am using primefaces 5.2. I tried multiple ways to establish this, but none did work so far. Here is one approach:

xhtml:

the idea is, to pass the element through a commandLink action attribute (which works fine for e.g. data tables):

 <fl:composition template="/WEB-INF/template.xhtml" xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core" xmlns:fl="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:p="http://primefaces.org/ui">
   <fl:define name="content">
      <h:form id="form">
         <p:diagram style="height:600px" value="#{flowDiagramBean.model}" var="el">
            <f:facet name="element">
               <p:commandLink actionListener="#{flowDiagramBean.onElementClicked}" update="@form" value="#{el.actionElementLabelText}">
                  <f:attribute name="element" value="#{el}"/>
               </p:commandLink>
            </f:facet>
         </p:diagram>
      </h:form>
   </fl:define>
</fl:composition>

The inital build up of the prototypes diagram:

@PostConstruct
   public void init() {
      setModel(new DefaultDiagramModel());
      getModel().setMaxConnections(-1);

      getModel().getDefaultConnectionOverlays().add(new ArrowOverlay(20, 20, 1, 1));
      FlowChartConnector connector = new FlowChartConnector();
      connector.setPaintStyle("{strokeStyle:'#C7B097',lineWidth:3}");
      getModel().setDefaultConnector(connector);

      ScreenFlowItemObj screenFlowItemObj = new ScreenFlowItemObj();
      screenFlowItemObj.setActionElementLabelText("test");

      Element start = new Element(screenFlowItemObj, "20em", "6em");
      start.addEndPoint(new BlankEndPoint(EndPointAnchor.BOTTOM));
      start.addEndPoint(new BlankEndPoint(EndPointAnchor.LEFT));

      Element trouble = new Element(screenFlowItemObj, "20em", "18em");
      trouble.addEndPoint(new BlankEndPoint(EndPointAnchor.TOP));
      trouble.addEndPoint(new BlankEndPoint(EndPointAnchor.BOTTOM));
      trouble.addEndPoint(new BlankEndPoint(EndPointAnchor.RIGHT));

      model.addElement(start);
      model.addElement(trouble);

   }

As you can see, the type ScreenFlowItemObj is the passed data object of each element.

The actionListener looks like this:

public void onElementClicked(ActionEvent event) {
      ScreenFlowItemObj screenFlowItemObj = (ScreenFlowItemObj) event.getComponent().getAttributes().get("element");
   }

Unfortunately on click of the commandLink the attribute "element" does not get put to the attribute map, so in the listener screenFlowItemObj resolves to null. Am i doing something wrong? Might there be another way to make this happen?

I am using primefaces 5.2 on a 1.7 tomee with JSF 2.2.

Thank you,

Gunnar


回答1:


There is no click event on 'elements' in the jsPlumb framework that PrimeFaces uses, so an 'ajax' select event is not possible, not directly anyway.

What you could do is:

  1. Give each element an explicit ID in your model (e.g. start.setId('start'))
  2. in your page after the diagram add some code that adds event handlers to the diagram elements (these are identifiable by their class (`ui-diagram-element)
  3. in the event handler call a PrimeFaces remote command that calls an actionListener with the id of the clicked element added to it

adding the eventhandler:

$(document).on('click', '.ui-diagram > .ui-diagram-element', function(info){
  console.log(info.target.id); // change this to call the remote command
});

How the info.target.id can be passed to a remote command can be read in this stackoverflow Q/A

I checked step 1 and 2 and used 3 before. It all works, I just did not combine them yet, but that should be not to difficult




回答2:


Thanks to Kukeltje approach, i was able to implement the functional reqiurement successfully:

xhtml:

<fl:composition template="/WEB-INF/template.xhtml"
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:fl="http://java.sun.com/jsf/facelets"
    xmlns:p="http://primefaces.org/ui">
    <fl:define name="content">
        <h:form id="screenFlowForm">
            <p:diagram value="#{flowDiagramBean.model}" var="el"
                style="height:600px">
                <f:facet name="element">
                    <h:outputText value="#{el.actionElementLabelText}" />
                </f:facet>
            </p:diagram>
            <p:remoteCommand name="elementClicked"
                actionListener="#{flowDiagramBean.onElementClicked}"/>
            <script type="text/javascript">
                        $(document).on('click',
                                '.ui-diagram > .ui-diagram-element',
                                function(info) {
                                    elementClicked([ {
                                        name : 'elementId',
                                        value : info.target.id
                                    } ]);
                                });
            </script>
        </h:form>
    </fl:define>
</fl:composition>

ActionListener:

public void onElementClicked() {
        logger.info(FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("elementId"));
    }

Works for me. I do not understand, why i have to pass the parameter in an one-element array, but ok - it is working.

Thank you for leading me to the right direction.

Gunnar



来源:https://stackoverflow.com/questions/35812682/jsf-primefaces-eventing-in-diagram-elements

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!