Giovanni M. Guidini
Giovanni M. Guidini

Reputation: 41

How to include mxFloorplan.js in mxGraph inside React application using Typescript?

So I'm trying to create a simple react application to render a mxGraph that I'm loading from a file. I can load the model, but some shapes aren't rendering correctly. The problem is that they are a specific shape, that are part of the floorplan package, and I can't find a way to include those shapes in my code.

ps.: I'm new to working with mxGraph.

Things I tried

  1. First thing I tried was downloading the mxFloorplan.js file into my application, and import it, like so:
// App.tsx
import './models/mxFloorplan'

const mx = factory({
  mxBasePath: './models'
})

let graph: mxGraph
...

Because the docs on extending mxShape show that I should register a new shape: mxCellRenderer.registerShape('customShape', CustomShape); and the mxFloorplan.js file does that. I then simply added this to the beggining of the file:

// mxFloorplan.js
import Graph, {
    mxShape,
    mxUtils,
    mxCellRenderer,
    mxPoint
} from 'mxgraph'
...

But then I get this error: Error mxCellRenderer is undefined

  1. Then I thought that I needed mxCellRenderer to be linked to my graph instance? So I tried moving one of the shape definitions into App.jsx to test:
// App.jsx
const mx = factory({
  mxBasePath: './models'
})

let graph: mxGraph

function mxFloorplanWall(bounds: any, fill: any, stroke: any, strokewidth: any)
{
    mx.mxShape.call(this); <-- Error: "Expected 2 args, but got one"
    this.bounds = bounds;
    this.fill = fill;
    this.stroke = stroke;
    this.strokewidth = (strokewidth != null) ? strokewidth : 1;
};

/**
* Extends mxShape.
*/
mx.mxUtils.extend(mxFloorplanWall, mxShape); <-- Error: "Property 'extend' does not exist on type mxUtils

// ... more code

mx.mxCellRenderer.registerShape(mxFloorplanWall.prototype.cst.WALL, mxFloorplanWall); <-- Error: mxFloorplanWall type not compatible with expected.

Really don't know how to solve these ones. On my research I only find references to mxCellRenderer.registerShape('name', CustomShape), so not really sure on the rest.

How it looks

Here is how the diagram looks like (ignore the arrow and labels, please): Diagram from draw.io

Here is what I'm actually rendering (the "black boxes" have shape=shape=mxgraph.floorplan.wallU): Diagram rendered in React

Upvotes: 1

Views: 332

Answers (1)

redfish4ktc
redfish4ktc

Reputation: 156

As described in https://jgraph.github.io/mxgraph/docs/js-api/files/shape/mxShape-js.html, you must pass a constructor to mxCellRenderer.registerShape

function CustomShape() { }

CustomShape.prototype = new mxShape();
CustomShape.prototype.constructor = CustomShape;

// To register a custom shape in an existing graph instance,
// one must register the shape under a new name in the graph’s cell renderer
// as follows:
mxCellRenderer.registerShape('customShape', CustomShape);
}

I guess your issues come from a wrong port of drawio code (that use a very old Javscript syntax) and is not related to React at all. It is currently unclear to me what you are exactly have implemented. Here are some hints.

If you use TypeScript, the mxCellRenderer.registerShape signature is enforced by the mxgraph types https://github.com/typed-mxgraph/typed-mxgraph/blob/v0.0.5-0/view/mxCellRenderer.d.ts#L83. When porting the mxFloorplanWall code to Typescript you should have a constructor like in the following (please avoid any!)

export class mxFloorplanWall extends mxShape { // or extends mx.mxShape depending how you manage mxgraph imports

  public constructor(bounds: mxRectangle, fill: string, stroke: string, strokewidth: number) {
    super(bounds, fill, stroke, strokewidth);
  }
...
}

Calling super directly set the arguments in super class and avoid the errors

// mx.mxUtils.extend(mxFloorplanWall, mxShape); <-- Error: "Property 'extend' does not exist on type mxUtils
// avoid mx.mxShape.call(this); <-- Error: "Expected 2 args, but got one"

Same if you use Javascript, prefer the ES6 class syntax to declare the mxFloorplanWall class.

Upvotes: 2

Related Questions