2


I have to use the Treant.js librairy in a React.js project but i have some issues to create diagram. In fact, the official website tell us that we have to import script like that:

<script src="vendor/raphael.js"></script>
<script src="Treant.min.js"></script>

I don't think that it's possible in react to import scripts like that... I have also seen that they made a node module (here). So I installed it and I tryed to import the lib like that

import Treant from 'treant-js'

Moreover, I have seen in an exemple that they generate diagram like that :

<script>
    new Treant( simple_chart_config );
</script>

Finally, the import worked but when i try to generate the diagram like that

{new Treant (this.state.diagram)}

I have this error : _treantJs2.default is not a constructor

Finally I have read this article : Integrating Treant-js in Angular2 Project and they say to import the lib from the files downloadable from the website but I don't think that it's possible to do that in react...

I already tryed many things but I'm a begginner with react, I'm certainly missing somethin obvious... If someone have an idea to help me, it would be nice :) Thank you

EDIT

I tryed to import the script directly in the render method of my react component :

 render(){
    return(
      <div>
        <script src="../lib/vendor/raphael.js"></script>
        <script src="../lib/Treant.js"></script>
        <script>
            new Treant( {this.state.diagram} );
        </script>
        <p>TEST</p>
      </div>
    )
 }

I think that's the good way but I still have this error : Objects are not valid as a React child

Community
  • 1
  • 1
Chili
  • 144
  • 2
  • 11
  • 1
    Don't include the scripts directly into your React components. First I suggest you read up about React and JSX by following a few tutorials. Then you have to understand the stack you are working with, since you are using the `import` syntax you must be working with some kind of module bundler (webpack for instance). Read up on how this works too. Good luck. – lleaff May 19 '17 at 10:29
  • Are you able to get this working – Nikhil Mahajan Aug 01 '18 at 08:11
  • @Nikhil Mahajan : see my answer below. I have just solved the problem today. – Lex Soft Jun 05 '19 at 12:46

2 Answers2

2

I have been doing research on several free organizational chart libraries. There are some that I tried: orgchart (by dabeng), d3-mitch-tree and Treant.js. I was successful in using the former two in my React app, although only for basic usage.

I just tried hard to do the same with Treant.js. It is not straight-forward. I had to learn quickly about CommonJs before working around the problems with Treant.js. After walking through its source code, I saw that it used CommonJs module system, so its javascript module have to be included using require statement, not import statement. You can see my code below.

But, when running the app, it displayed error:

"Raphael is not defined"

When debugging, I found the cause of the error. Treant.js file depends on raphael library, which is used in its handleOverflow function. So I added one line in that function of Treant.js file to include the dependency as follows:

// Create Raphael instance, set scrollbars if necessary
handleOverflow: function(treeWidth, treeHeight) {
    // I added this statement which didn't exist in original file
    var Raphael = require("./vendor/raphael")
    // ...

Here is my code :

import React from "react";
import "treant-js/Treant.css"
import "treant-js/basic-example.css"

var Treant = require("treant-js/Treant")

export default class MyTreantJs extends React.Component {
constructor(props) {
    super(props);
    this.treant = null
    this.chart_config = null
}

componentDidMount() {
    const loginpathname = window.sessionStorage.getItem("appHomePathName", homepathname)
    const index = loginpathname.indexOf("public")
    const homepathname = loginpathname.substring(0,index)
    const imageurl = homepathname + "/public/images/headshots/"

    const config = {
        container: "#basic-example",            
        connectors: {
            type: 'step'
        },
        node: {
            HTMLclass: 'nodeExample1'
        }
    },
    ceo = {
        text: {
            name: "Mark Hill",
            title: "Chief executive officer",
            contact: "Tel: 01 213 123 134",
        },
        image: imageurl + "2.jpg"
    },

    cto = {
        parent: ceo,
        text:{
            name: "Joe Linux",
            title: "Chief Technology Officer",
        },
        stackChildren: true,
        image: imageurl + "1.jpg"
    },
    cbo = {
        parent: ceo,
        stackChildren: true,
        text:{
            name: "Linda May",
            title: "Chief Business Officer",
        },
        image: imageurl + "5.jpg"
    },
    cdo = {
        parent: ceo,
        text:{
            name: "John Green",
            title: "Chief accounting officer",
            contact: "Tel: 01 213 123 134",
        },
        image: imageurl + "6.jpg"
    },
    cio = {
        parent: cto,
        text:{
            name: "Ron Blomquist",
            title: "Chief Information Security Officer"
        },
        image: imageurl + "8.jpg"
    },
    ciso = {
        parent: cto,
        text:{
            name: "Michael Rubin",
            title: "Chief Innovation Officer",
            contact: {val: "we@aregreat.com", href: "mailto:we@aregreat.com"}
        },
        image: imageurl + "9.jpg"
    },
    cio2 = {
        parent: cdo,
        text:{
            name: "Erica Reel",
            title: "Chief Customer Officer"
        },
        link: {
            href: "http://www.google.com"
        },
        image: imageurl + "10.jpg"
    },
    ciso2 = {
        parent: cbo,
        text:{
            name: "Alice Lopez",
            title: "Chief Communications Officer"
        },
        image: imageurl + "7.jpg"
    },
    ciso3 = {
        parent: cbo,
        text:{
            name: "Mary Johnson",
            title: "Chief Brand Officer"
        },
        image: imageurl + "4.jpg"
    },
    ciso4 = {
        parent: cbo,
        text:{
            name: "Kirk Douglas",
            title: "Chief Business Development Officer"
        },
        image: imageurl + "11.jpg"
    }

    this.chart_config = [
        config,
        ceo,
        cto,
        cbo,
        cdo,
        cio,
        ciso,
        cio2,
        ciso2,
        ciso3,
        ciso4
    ];

    this.treant = new Treant(this.chart_config)
}

render(){
  return (
    <div id="basic-example" style={{height:"600px", width:"1200px"}}></div>
  );
}

}

Here, the basic-example.css file was copied from the examples folder. The configuration for the chart was taken from the examples folder too. I used sessionStorage of the browser to find location of the images. So far, my code worked well.

EDIT : The above code still doesn't work. Do not modify the Treant.js source code. Instead, use the following :

import React from "react";
import "treant-js/Treant.css"
import "treant-js/examples/basic-example/basic-example.css"
import Raphael from "raphael";

window.Raphael = Raphael

var Treant = require("treant-js/Treant")
Treant = Treant.Treant

Treant doesn't import raphael, but it expects raphael instance to be globally available. That's why after importing raphael in our app we need the statement :

window.Raphael = Raphael

Notice the statement :

Treant = Treant.Treant

This is necessary, as Treant (when looking at the console) is an object that has property also named Treant.

Kaspar Lee
  • 5,446
  • 4
  • 31
  • 54
Lex Soft
  • 2,308
  • 2
  • 13
  • 13
  • Lex Soft @lex-soft, can you please explain how you integrated d3-mitch-tree into react? I am trying but without success :( thanks! – pinker Nov 04 '19 at 17:17
  • @pinker I think it's better to explain it by giving you my code. But I cannot give it in the answers section, whereas this comment section cannot contain the whole code. Maybe by email if you don't mind. – Lex Soft Nov 05 '19 at 13:43
  • @pinker I have just created a small app in CodeSandbox : https://codesandbox.io/s/withered-tdd-edf73 – Lex Soft Nov 05 '19 at 15:41
  • Thank you @lex-soft! I will probably create a npm for a react version of this library. – pinker Nov 06 '19 at 14:05
  • @pinker It's a pleasure. Good luck with your project. – Lex Soft Nov 06 '19 at 14:25
2

I'm not sure if this breaks any rules - this might be better as a comment, I honestly don't know, but unfortunately I can't post a comment due to lack of reputation, but really wanted to post an update in case anyone else happens upon this. The answer above by Lex Soft got me almost all the way to the solution, but I had to use the library treantjs (https://www.npmjs.com/package/treantjs) instead of treant-js.

Basically my imports look like this instead:

import 'treantjs/Treant.css';
import Raphael from 'raphael';
import React from 'react';
import Treant from 'treantjs/Treant';

Treant = window.Treant; // this package doesn't load as a module properly...
window.Raphael = Raphael;

The treant-js library is a little older and is not the official package, so it's not up to date. I specifically was having an issue of the chart only showing the first node when I unmounted the node and mounted a new one.

Anne W.
  • 68
  • 1
  • 7