hungtcs / mxgraph-type-definitions

mxgraph type definitions
https://www.npmjs.com/package/mxgraph-type-definitions
Apache License 2.0
20 stars 8 forks source link

add more detailed setup information #28

Open zhujik opened 4 years ago

zhujik commented 4 years ago

Hi, I'm developing a react app with typescript and want to use mxgraph. I'm not super proficient in typescript but so far I had no trouble setting up libraries. With mxgraph-type-definitions however it seems this is targeted to advanced typescript programmers who exactly know where to make some adjustments.

I followed the instructions for the usage (using npm) and in my Intellij IDEA, the type definitions appear and in the code it is parsed. However, when running the app the objects are undefined. For example, mxClient.isBrowserSupported() is parsed by the IDE and I can click on the function to go to the definition (which is the mxgraph-type-definitions module). However, on runtime I get the error "Cannot read property 'isBrowserSupported' of undefined". I'm importing the mxgraph elements like so: import { mxClient } from 'mxgraph'

Please advice on how to setup the project so that the definitions are compiled.

tbouffard commented 4 years ago

Hi @zhujik You are probably missing the mxgraph JavaScript dependency. The mxgraph-type-definitions lib contains no code but only definitions so you need the js lib at runtime. This can be managed via something like npm install mxgraph

About the current documentation status, it is clearly missing details and should be straightforward for anybody Prior discussions on this topic happened in #10 and I plan to provide Pull Request in this area soon I have been able to integrate the definitions by setting a typeroots entry in my tsconfig.json file as described in https://github.com/ivamax9/angular-mxgraph-demo but I am not very happy with it: I would lke to not define a typeRoot entry and use regular imports. Could you share your tsconfig.json or any project settings (or a git repo) to explain how you proceeded to setup mxgraph?

hungtcs commented 4 years ago

Hi @zhujik, Sorry for the late reply, I'm busy looking for a new job recently. As @tbouffard said, you can refer to #10 if you are using some typescript wrapper for mxgraph. Or refer to this example I am created via crearte-react-app without typescript wrapper, I use git submodule to load the type declaration to keep up to date.

zhujik commented 4 years ago

Hi @tbouffard and @hungtcs and thank you for your quick reply.

My setup is currently as follows:

package.json:

...
  "dependencies": {
...
    "mxgraph": "^4.1.1",
...
}
...
  "devDependencies": {
    "@types/jest": "^26.0.3",
    "@types/node": "*",
    "@types/react": "^16.9.41",
    "@types/react-dom": "^16.9.8",
    "@types/react-native": "^0.62.16",
    "@types/react-test-renderer": "^16.9.2",
    "mxgraph-type-definitions": "^1.0.3",
    "typescript": "^3.9.6"
  }

My tsconfig.json without changes looks like so:

{
  "compileOnSave": false,
  "compilerOptions": {
    "suppressExcessPropertyErrors": true,
    "declaration": false,
    "strictNullChecks": false,
    "sourceMap": true,
    "skipLibCheck": true,
    "jsx": "preserve",
    "target": "ES6",
    "module": "esnext",
    "strict": false,
    "lib": [
      "DOM",
      "ES6"
    ],
    "allowJs": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "forceConsistentCasingInFileNames": true,
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true
  },
  "include": [
    "./src"
  ]
}

I tried adding the following:

    "types": [
      "mxgraph-type-definitions"
    ],

or

   "typeRoots": [
      "node_modules/mxgraph-type-definitions",
      "node_modules/@types"
    ],

with the same result.

My sample app looks like so:

import React, {Component} from "react";

// according to mxgraph, this is the way to import mxgraph loaded from npm
var mx = require("mxgraph")({
    mxImageBasePath: "./src/images",
    mxBasePath: "./src"
});

export default class App extends Component {

    private containerRef: React.RefObject<HTMLDivElement>;

    private graph: mxGraph;

    constructor(props) {
        super(props);
        this.state = {};
        this.LoadGraph = this.LoadGraph.bind(this);
        this.containerRef = React.createRef()
    }

    componentDidMount() {
        this.LoadGraph();
    }

   async LoadGraph() {
        let container = this.containerRef.current;

        // Checks if the browser is supported
        if (!mx.mxClient.isBrowserSupported()) {
            // Displays an error message if the browser is not supported.
            // mx.mxUtils.error("Browser is not supported!", 200, false, null);
        } else {
            // Disables the built-in context menu
            mx.mxEvent.disableContextMenu(container);

            // Creates the graph inside the given container
            this.graph = new mx.mxGraph(container);

            // Enables rubberband selection
            new mx.mxRubberband(this.graph);

            // Gets the default parent for inserting new cells. This is normally the first
            // child of the root (ie. layer 0).
            const parent = this.graph.getDefaultParent();

            // Enables tooltips, new connections and panning
            this.graph.setPanning(true);
            this.graph.setTooltips(true);
            this.graph.setConnectable(true);
            this.graph.setEnabled(true);
            this.graph.setEdgeLabelsMovable(false);
            this.graph.setVertexLabelsMovable(false);
            this.graph.setGridEnabled(true);
            this.graph.setAllowDanglingEdges(false);

            this.graph.getModel().beginUpdate();
            try {
                let nodeMap = new Map<string, mxCell>();

                let response = await DataService.retrieveAllNodes("test");
                response.data.forEach(
                    node => {
                        let vertex = this.graph.insertVertex(parent, null, node.name, 0, 0, 50, 50,  "rounded=1;strokeColor=red;fillColor=orange");
                        nodeMap.set(node.id, vertex);
                    });

                let transitionResponse = await DataService.retrieveAllTransitions("test")
                transitionResponse.data.forEach(
                            transition => {

                                let from = nodeMap.get(transition.from.id);
                                let to = nodeMap.get(transition.to.id);

                                this.graph.insertEdge(parent, null, null, from, to);
                            });

                //data
            } finally {
                // Updates the display
                this.graph.getModel().endUpdate();
            }

        ... etc. sample code taken from an mxgraph demo ...
        }
    }

    render() {
        return <div className="graph-container" ref={this.containerRef} />;
    }
}

With this setup, the applications tarts and mxgraph is displayed. I also noticed that compile-time type checkings work. For example, if I change let nodeMap = new Map<string, mxCell>(); to let nodeMap = new Map<string, mxGraph>();, I get the correct error that vertex could not be inserted into the map because mxCell is not assignable to mxGraph. However, the type definitions are not read by IntellIj IDEA, there is no code completion. Frankly I don't know how the objects from the mx namespace (like mx.mxGraph) are connected to the type definitions provided by mxgraph-type-definitions. Could you give some insights?

hungtcs commented 4 years ago

Hi @zhujik, I did some attempts, but there are still many shortcomings, we will create a new issues to discuss these problems.

https://github.com/hungtcs/react-with-mxgraph--ts-factory

hungtcs commented 4 years ago

MoveTo #29

tbouffard commented 4 years ago

@hungtcs I suggest to keep this issue opened there is definitely a need for more documentation about how to use mxgraph with typescript and the definitions npm package. For sure there is currently an issue with the mxClient class (let's manage this through #29) but appart from that, it is possible to use the npm mxgraph-type-definitions package.

@zhujik, What I currently do (this is what https://github.com/ivamax9/angular-mxgraph-demo does as well)

I am planning to create a demo vanilla typescript project to demonstrate that, but I don't have time for that now

mxgraph settings

// options to set
const options = {
  mxLoadResources: false,
  mxLoadStylesheets: false,
};
// available options
const optionKeys = [
  'mxBasePath',
  'mxDefaultLanguage',
  'mxForceIncludes',
  'mxImageBasePath',
  'mxLanguage',
  'mxLanguages',
  'mxLoadResources',
  'mxLoadStylesheets',
  'mxResourceExtension',
];
optionKeys.forEach(key => {
  window[key] = options[key];
});
tbouffard commented 4 years ago

@zhujik do you still have issues with your IntelliJ IDE (except with the mxClient import no available because of #29 )? I can probably help you on this if needed.

zhujik commented 4 years ago

@tbouffard sorry for the late response. I settled for the solution with the subrepository right now because I have to use the latest commit on master for my project, but I want to revisit the npm package later again and also check out that new solution "typed-mxgraph". I really appreciate all the work that has been put in here by you guys and if I find something to contribute, I'll gladly do so.