Reputation: 372
When i use any of the mxgraph methods/values my mxgraph is 'undefined'
I already tried the viks answer on this thread : How to integrate mxGraph with Angular 4?
but even if this give me the typings and intellisense is working fine i still have my mxgraph undefined.
I should mention that this is a brand new angular project and i just followed viks's tutorial to get here.
import { mxgraph } from "mxgraph";
declare var require: any;
const mx = require('mxgraph')({
mxBasePath: 'assets/mxgraph'
});
@Component({...})
export class LetestComponent implements OnInit {
ngOnInit() {
var container = document.getElementById('graphContainer');
var graph = new mx.mxGraph(container);
}
}
with this in the HTML file
<div id="graphContainer"></div>
I shouldn't have any error there and i should be able to use mx to call any mxGraph methods.
When i compile the code it seems to be working fine, but then when i look at it on the browser's console i have :
"Uncaught TypeError: Cannot set property 'mxBasePath' of undefined at build.js:11 at Module../src/app/letest/letest.component.ts (letest.component.ts:6)"
I don't know if it's a problem because i'm using angular 8 where viks's answer is for angular 4 or if it's something with the typescript syntax which could have changed since then.
If someone could help me with this it would be awesome,
thanks in advance !
Edit: i'm still trying a bunch of things but i think i don't really understand the "require('mxgraph')" part, it's in there that there is the undefined even thought the mx constant is not undefined if i log it to the console in the class. Maybe there's a new way in angular 8 to do the same thing?
I should also mention that the Types of mxgraph seems to be working fine in Visual Code studio, it's like i have the definitions but not the actual code.
Edit 2: After diving in a bit more i got it working with https://itnext.io/how-to-integrate-mxgraph-with-angular-6-18c3a2bb8566 but the problem is that these Types are 4 years old so it lack a huge numbers of methods/variables from the latest mxgraph version.
What i found out is that in these types there's just (Is Working)
declare class mxGraph{..}
Whereas the newest Types use (Is not working)
declare namespace mxgraph {
export class mxGraph {..}
}
Could someone explain the differences please?
Upvotes: 3
Views: 3084
Reputation: 360
I also couldn't find any resources related to this. So I made several npm packages by myself. You can try to use one of these packages in your Angular project. These are just typescript wrappers of the original mxgraph library.
https://www.npmjs.com/package/ts-mxgraph
https://www.npmjs.com/package/ts-mxgraph-factory
https://www.npmjs.com/package/ts-mxgraph-typings
I used the following method in my project. I created mxgraph.overrides.ts file inside the project and imported mxgraph prototypes. You can also extend the original methods of the library.
import '../../assets/deflate/base64.js'
import '../../assets/deflate/pako.min.js';
import { mxgraph, mxgraphFactory } from "ts-mxgraph";
const mx = mxgraphFactory({
mxBasePath: 'mxgraph',
mxLoadResources: false,
mxLoadStylesheets: false,
});
declare const Base64: any;
declare const pako: any;
let mxActor: any = mx.mxActor;
let mxArrow: any = mx.mxArrow;
let mxArrowConnector: any = mx.mxArrowConnector;
let mxGraph: any = mx.mxGraph;
let mxClient: any = mx.mxClient;
let mxUtils: any = mx.mxUtils;
...
// extends mxgraph prototypes
mxGraph.prototype.updatePageBreaks = function(visible, width, height) {
...
}
// Adds panning for the grid with no page view and disabled scrollbars
const mxGraphPanGraph = mxGraph.prototype.panGraph;
mxGraph.prototype.panGraph = function(dx, dy) {
mxGraphPanGraph.apply(this, arguments);
...
}
...
export {
mxClient,
mxUtils,
mxGraph,
...
}
// and then import these where you want to use them
import {
mxClient,
mxUtils,
mxGraph,
mxGraphModel,
mxGeometry,
mxConstants,
mxCell,
mxDictionary,
mxCellEditor,
mxStyleRegistry
} from './mxgraph.overrides';
import { IMAGE_PATH, STYLE_PATH, STENCIL_PATH, urlParams } from '../config';
declare var Base64: any;
declare var pako: any;
export class Graph extends mxGraph {
...
}
Upvotes: 0
Reputation: 3753
MxGraph is a library written in JavaScript. TypeScript, as used by Angular, has types (as the name suggests) and then compiles down to JavaScript (which does not have static types). For TypeScript to be aware of the correct Types etc. in a JS-library, you need some type definitions.
As far as I know, no such type definitions exist for MxGraph.
That doesn't have to stop us, we can still use JS Libraries! Here is how I'm using MxGraph in my project:
I have a normal dependency in my package.json
: "mxgraph": "^3.9.12",
But we also need to tell Angular where to find the JS-Script! Look at my 'angular.json' file:
{
"projects": {
"architect": {
"build": {
"options": {
"assets": [
{ "glob": "**/*", "input": "src/assets/", "output": "/assets/" },
{ "glob": "favicon.png", "input": "src/", "output": "/" },
{ "glob": "**/*", "input": "./node_modules/mxgraph/javascript/src", "output": "/assets/mxgraph" }
]
"scripts": [
"node_modules/mxgraph/javascript/mxClient.js"
]}
}
}
}
}
Note: I have only included the relevant bit. I needed to tell angular that this external Script should be included and available. See docs
My Template (mygraph.component.html) looks a bit different:
<div #graphContainer
style="overflow:hidden;width:100%;height:100%; padding: 10px;">
</div>
You see, Angular uses the '#'-Symbol for template references!
Here my "mygraph.component.ts":
import 'mxgraph/javascript/mxClient.js';
/**
* externally (in mxClient) defined vars
*/
declare var mxClient: any;
declare var mxUtils: any;
declare var mxRubberband: any;
declare var mxConstants: any;
declare var mxPerimeter: any;
declare var mxEdgeStyle: any;
const mx = require('mxgraph')({
mxBasePath: 'assets/mxgraph'
});
@Component({
selector: 'app-graph',
templateUrl: './graph.component.html',
styleUrls: ['./graph.component.scss']
})
export class GraphComponent {
@ViewChild('graphContainer', { static: true }) graphContainer: Element;
constructor(private http: HttpClient) {}
// This I'm calling in my custom logic
private draw() {
// Checks if the browser is supported
if (!mxClient.isBrowserSupported()) {
mxUtils.error('Browser is not supported!', 200, false);
} else {
// Creates the graph inside the given container
this.graphContainer['nativeElement'].innerHTML = '';
const graph = new mx.mxGraph(this.graphContainer['nativeElement']);
// Get and clone style, just for demonstration
let style = graph.getStylesheet().getDefaultVertexStyle();
let style2 = mxUtils.clone(style);
graph.getStylesheet().putCellStyle('myStyle', style2);
// Gets the default parent for inserting new cells. This
// is normally the first child of the root (ie. layer 0).
const defaultParent = graph.getDefaultParent();
// Adds cells to the model in a single step
graph.getModel().beginUpdate();
try {
// Do some drawing
// graph.insertVertex(...
// graph.insertEdge(...
} finally {
// Updates the display
graph.getModel().endUpdate();
// Make Graph not changeable by User
graph.setEnabled(false);
}
}
}
}
While this is not a complete example (I have just taken some interesting bits from my code), it should help you get setup and started. For the actual drawing, refer to the MxGraph documentation.
Upvotes: 5