projectstorm / react-diagrams

a super simple, no-nonsense diagramming library written in react that just works
https://projectstorm.cloud/react-diagrams
MIT License
8.75k stars 1.18k forks source link

How to use events #164

Closed Baudin999 closed 6 years ago

Baudin999 commented 6 years ago

Hi there,

Is there documentation on how to work with events? I want to add some events to my project but don't even know where to begin.

If you could me give me some information on the different events and how to attach them I would happily write the documentation and add a PR.

Cheers

lucanisi commented 6 years ago

I figured it out by myself reading the source code for the events and a sample for adding the listener. You can add the listener by using the addListener method

var model=new DiagramModel();
model.addListener({
     nodesUpdated: function(e){
       // Do something here
     },
     zoomUpdated: function(e){
      // Do something here
     },
});

And here is the event list 😃 Events for DiagramModel:

nodesUpdated
linksUpdated
offsetUpdated
zoomUpdated
gridUpdated
selectionChanged
entityRemoved

Events for LinkModel:

sourcePortChanged
targetPortChanged
selectionChanged
entityRemoved

Events for NodeModel and PointModel:

selectionChanged
entityRemoved

Hope it helped!

ganesh-sankey commented 6 years ago

@lucanisi when I tried to call another function in '// Do something here' part, It through error as 'error function is undefined'. when I tried console.log for print e value, it was working. how can I call function in that //Do something part.

lucanisi commented 6 years ago

@ganesh-sankey can you paste the code throwing you the error here? what are you trying to accomplish?

ganesh-sankey commented 6 years ago

@lucanisi I have resolved the issue. There was some syntax issue from my side. I was actually calling function inside //do something. like nodeUpdated: function (e) { this.myfunction (); },

Instead I put it as - nodeUpdated :{ this.myfunction ();},

It worked for me. Thank you for putting above documentation. It was huge help to understand how to add listeners

ganesh-sankey commented 6 years ago

@lucanisi Is there way to add listener to dynamically created links between nodes. means when you create link between nodes in diagram widget using drag from one port to another? What I thought that to add listener to model but then I will not get entityRemoved and selectionChanged event for that created link. Any suggestions?

lucanisi commented 6 years ago

@ganesh-sankey you can add the listener to a new link inside the linksUpdated event

model.addListener({
   linksUpdated: function(event){
      event.link.addListener({
         // New created link events here
      });
   }
});
ganesh-sankey commented 6 years ago

@lucanisi I got stuck up when implementing further functionality using dynamically created links. Now I need to add label to that created link on selectionChanged. Here is the code:

  addListenerToModel (diagramModel: DiagramModel) {
    diagramModel.addListener({
      /**
       * linksUpdated
       * Perform action when link is updated
       */
      linksUpdated: e => {
        this.linksUpdated(e);
      }
    });
  }
  linksUpdated (event: Object) {
    event.link.addListener({
      /**
       * selectionChanged
       * Perform action when link is selected
       */
      selectionChanged: e => {
        event.link.addLabel('welcome');
      },
      /**
       * entityRemoved
       * Perform action when link is removed
       */
      entityRemoved: e => {
        //
      }
    });
  }

I got error as Uncaught TypeError: path.getTotalLength is not a function. Did I write something wrong? Any idea?

ganesh-sankey commented 6 years ago

@lucanisi Thanks bruhh. Resolved the issue. It was related path.getTotalLength() function. since I modified the LinkWidget component for arrow head functionality which returns <g> tag instead of <path> tag. so I need to unwrap the path from <g> tag in those functions and use it.

dmigo commented 6 years ago

It would be awesome to get notified when some links appear/being changed. What is the best event for that purpose?

Crecket commented 6 years ago

For some reason the eventListeners no longer work after the initial render. It shows multiple linksUpdated and nodesUpdated events the first time I add new nodes and links. But any other events are never triggered when I interact with the diagram.

Adding event listeners to the separate links or nodes individually also does not seem to work.

model.addListener({
    nodesUpdated: e => console.log("nodesUpdated", e),
    linksUpdated: e => console.log("linksUpdated", e),

    // these are never triggered
    zoomUpdated: e => console.log("zoomUpdated", e),
    gridUpdated: e => console.log("gridUpdated", e),
    offsetUpdated: e => console.log("offsetUpdated", e),
    entityRemoved: e => console.log("entityRemoved", e),
    selectionChanged: e => console.log("selectionChanged", e)
});
gj1118 commented 6 years ago

I agree , I cannot see any selectionChanged event getting fired. I just copied the above code verbatim .

hamsa95 commented 5 years ago

SelectionChanged events is fired using following code https://blog.sourcerer.io/build-interactive-diagrams-with-storm-react-diagrams-f172ae26af9d

node2.addListener({ selectionChanged: () => { console.log("selectionchanged--------------")}});

alexandernst commented 4 years ago

If you got here from Google, addListener was renamed to registerListener

jduncanRadBlue commented 4 years ago

Does anyone know how to label the link with data that sits inside the node data (node data was attached upon creation of node)? When the node is created, I attach a JSON object to the node for hopes of being able to access later for purposes of posting an API call. When the node event for onDrop is called, I can see the data being logged in the event.dataTrasfer.getData() call, but on the linksUpdated event, I can't find said data?

I can't seem to dig through linksUpdated event to find the node data?

diagramEngine.getModel().registerListener({
              linksUpdated: (event) => {console.log(event)}
            });

Full BodyWidget Code:

import * as React from 'react';
import PropTypes from 'prop-types';
import * as _ from 'lodash';
import '../styles/App.css';
import createEngine, {
  DiagramModel,
  DefaultNodeModel,
  DefaultLinkModel,
} from '@projectstorm/react-diagrams';
import { CanvasWidget } from '@projectstorm/react-canvas-core';
import styled from '@emotion/styled';
import TrayWidget from './TrayWidget';

export default function BodyWidget() {
  const diagramEngine = createEngine();
  const activeModel = new DiagramModel();
  diagramEngine.setModel(activeModel);

  const [engine, setEngine] = React.useState(diagramEngine);

  const handleUpdateEngine = (engine) => {
    setEngine(engine);
  };

  const style = {
    Body: {
      flexGrow: 1,
      display: 'flex',
      flexDirection: 'column',
      minHeight: '100%',
    },
    Header: {
      display: 'flex',
      background: 'rgb(30, 30, 30)',
      flexGrow: 0,
      flexShrink: 0,
      color: 'white',
      fontFamily: 'Helvetica, Arial, sans-serif',
      padding: '10px',
      alignItems: 'center',
    },
    Content: {
      display: 'flex',
      flexGrow: 1,
    },
    Layer: {
      position: 'relative',
      flexGrow: 1,
      height: '100vh',
      width: '100%',
      background: 'rgb(30, 30, 30)',
    },
  };

  return (
    <div style={style.Body}>
      <div style={style.Header}>
        <div className="title">DnD demo</div>
      </div>
      <div style={style.Content}>
        <TrayWidget applications={applicationDefinition} />
        <div
          style={style.Layer}
          onDrop={(event) => {
            const data = JSON.parse(
              event.dataTransfer.getData('storm-diagram-node')
            );

            const nodesCount = _.keys(diagramEngine.getModel().getNodes())
              .length;
            let node = null;
            console.log(data);
            if (data.nodeType === 'in') {
              node = new DefaultNodeModel(
                data.name,
                'rgb(192,255,0)'
              );
              node.addInPort('In');
            } else {
              node = new DefaultNodeModel(
                data.name,
                'rgb(0,192,255)'
              );
              node.addOutPort('Out');
            }
            const point = diagramEngine.getRelativeMousePoint(event);
            node.setPosition(point);

            diagramEngine.getModel().addNode(node);
            diagramEngine.getModel().registerListener({
              linksUpdated: (event2) => {console.log(event2)}
            });
            handleUpdateEngine(diagramEngine);
            diagramEngine.repaintCanvas();
          }}
          onDragOver={(event) => {
            console.log(event)
            event.preventDefault();
          }}
        >
          <CanvasWidget className="canvas" engine={engine} />
        </div>
      </div>
    </div>
  );
}
berabulut commented 4 years ago

@jduncanRadBlue Do you know a way to find connected nodes?

jduncanRadBlue commented 4 years ago

@berabulut I haven't found a way. I opened a new issue:

740

No comments yet. :(

berabulut commented 4 years ago

@jduncanRadBlue if you have node id this works. You can reach the data of source port and target port.

340

jduncanRadBlue commented 4 years ago

@berabulut do you happen to have example code snipped of how to accomplish that? I've noticed on the event linksUpdated, nothing is fired for when a link is actually successfully connected to a port. It fires when a link is started its drag, but no connection event.

berabulut commented 4 years ago

@jduncanRadBlue I don't have a code that fires an event after a connection. ATM I can only access the data after board force updates itself. I can send you the code if you want to look at what i have.

jduncanRadBlue commented 4 years ago

@berabulut That would be very helpful actually!

drnguyenn commented 3 years ago

Hi. I'm wondering is there any way to know when a new point is created or removed on a link. I have tried to track the DiagramModel by registering linksUpdated and also eventDidFire listeners, but none of them seems to work.

rzfzr commented 2 years ago
        this.props.app.getDiagramEngine().getModel().registerListener({
            eventDidFire: () => { console.log('event did fire') }
        });

This kinda of works, but it does not fire when a link is made...

amith2368 commented 2 years ago

If you are looking for event listener when a connection is made, here you go

model.registerListener({
        linksUpdated: (event) => {
           event.link.registerListener({
               targetPortChanged: (event) => {
                   console.log('Link Changed');
               }
           })
        }
    });