Search code examples
reactjsfluxjointjs

Include JointJS diagram in React/Flux projects


I'm trying to include a JointJS diagram in my React+Flux project. I started from an existing demo available there.

My idea is to embed the diagram in an higher level component that will be reused inside my project.

The structure that I came up with is the following:

index.html

...
<body>
<section id="mySec"></section>
...

app.js

...
ReactDOM.render(
    <JointJSDiagram id="1"/>,
    document.getElementById('mySec')
);

JointJSDiagram.react.js

...
var JointJSDiagramStore = require('../stores/JointJSDiagramStore');

class JointJSDiagram extends React.Component {
...
    componentDidMount() {
        var el = this.refs[this.props.placeHolder];
        document.addEventListener("DOMContentLoaded", function(elt){
                return function(){JointJSDiagramStore.buildDiagram(elt)};
            }(el), false);
    }
...
    render() {
        return (<div ref={this.props.placeHolder}/>);
    }
...
}

module.exports = JointJSDiagram;

JointJSDiagramStore.js

...
var AppDispatcher = require('../dispatcher/AppDispatcher');
var EventEmitter = require('events').EventEmitter;
var assign = require('object-assign');

var _graph = new joint.dia.Graph();
var _paper = new joint.dia.Paper({
    width: 600,
    height: 200,
    model: _graph,
    gridSize: 1
});


var JointJSDiagramStore = assign({}, EventEmitter.prototype, {
...
    buildDiagram: function(el) {
        _paper.el = el;
       // In here I used the code from: http://www.jointjs.com/demos/fsa
       function state(x, y, label) {

           var cell = new joint.shapes.fsa.State({
           position: { x: x, y: y },
           size: { width: 60, height: 60 },
           attrs: {
              ...
              ...
              ...
       link(star,  block, 'other', [{x: 650, y: 290}]);
       link(star,  code,  '/',     [{x: 490, y: 310}]);
       link(line,  line,  'other', [{x: 115,y: 100}, {x: 250, y: 50}]);
       link(block, block, 'other', [{x: 485,y: 140}, {x: 620, y: 90}]);
       link(code,  code,  'other', [{x: 180,y: 500}, {x: 305, y: 450}]);
    },
...
});
...
module.exports = JointJSDiagramStore;

The problem is that nothing is visualized except for some (7) warnings stating:

Warning: ReactDOMComponent: Do not access .getDOMNode() of a DOM node; instead, use the node directly. This DOM node was rendered by JointJSDiagram.

UPDATE

If I explicitly use the id instead of refs like this:

JointJSDiagramStore.js

...
componentDidMount() {
    var el = document.getElementById(this.props.placeHolder);
    document.addEventListener("DOMContentLoaded", function(elt){
            return function(){JointJSDiagramStore.buildDiagram(elt)};
        }(el), false);
    JointJSDiagramStore.addChangeListener(this._onChange);
}
...
render() {
        return (<div id={this.props.placeHolder}/>);
}
...

I don't receive Warnings anymore, but nothing is still displayed on the placeholder div.


Solution

  • This quick test worked for me. I'm using react 0.14.3

    class Graph extends React.Component {
    
        constructor(props) {
            super(props);
            this.graph = new joint.dia.Graph();
        }
    
        componentDidMount() {
            this.paper = new joint.dia.Paper({
                el: ReactDOM.findDOMNode(this.refs.placeholder),
                width: 600,
                height: 200,
                model: this.graph,
                gridSize: 1
            });
    
            const rect = new joint.shapes.basic.Rect({
                position: { x: 100, y: 30 },
                size: { width: 100, height: 30 },
                attrs: {
                    rect: { fill: 'blue' },
                    text: { text: 'my box', fill: 'white' }
                }
            });
    
            const rect2 = rect.clone();
            rect2.translate(300);
    
            const link = new joint.dia.Link({
                source: { id: rect.id },
                target: { id: rect2.id }
            });
    
            this.graph.addCells([rect, rect2, link]);
        }
    
        render() {
            return <div ref="placeholder" ></div>;
        }
    }