typed-mxgraph / typed-mxgraph

mxGraph typescript declarations

Home Page:https://www.npmjs.com/package/@typed-mxgraph/typed-mxgraph

Repository from Github https://github.comtyped-mxgraph/typed-mxgraphRepository from Github https://github.comtyped-mxgraph/typed-mxgraph

Type Error is thrown on invoking fatory function imported from mxgraph in Angular 13

Dhawaldeep opened this issue · comments

Following type error is thrown while invoking factory function imported from mxgraph

Uncaught TypeError: Cannot set properties of undefined (setting 'mxBasePath')

This happens only on Angular 13 stable version and not on angular 12.

Please see the below public repository link & code snippets for reference
https://github.com/Dhawaldeep/mxgraph-angular-tteen

src/app/mxgraph-engine/mxgraph.ts

import factory from 'mxgraph';
declare global {
  interface Window {
    mxBasePath: string;
  }
}

window['mxBasePath'] = '../../assets/mxgraph';

export default factory({
  mxBasePath: '../../assets/mxgraph',
});

src/app/mxgraph-engine/index.d.ts

declare module 'mxgraph';

src/app/app.component.ts

.........
import mx from './mxgraph-engine/mxgraph';
import '@typed-mxgraph/typed-mxgraph';
.........
export class AppComponent implements AfterViewInit {
  @ViewChild('mxgraphEl') mxgraphEl: ElementRef<HTMLDivElement>;

  ngAfterViewInit(): void {
    if(mx.mxClient.isBrowserSupported()) {
      console.log('Yes! Yes!');
    }
    const graph = new mx.mxGraph(this.mxgraphEl.nativeElement);
    const model = graph.getModel();
    model.beginUpdate();
    try {
      graph.insertVertex(graph.getDefaultParent(), '', 'TEST', 0, 0, 100, 100);
    } finally {
      model.endUpdate();
    }
  }
}

src/app/app.component.html

<div #mxgraphEl></div>

package.json

....
dependencies: {
..,,.
 "mxgraph": "^4.2.2",
....
},
.....
devDependencies: {
.....
"@typed-mxgraph/typed-mxgraph": "^1.0.5",
.....
}

Thank you.

Thanks for your feedback @Dhawaldeep, I can reproduce this bug.

I can't find much Angular related details, but it looks like the compiler has stricter restrictions on the lib.

There are two main problems here.

The first is that the this pointer of the factory function becomes to undefined, suspected to be caused by the new version of angular-cli. a crude workaround is invoke factory via call factory.call(window, { ... });

node_modules/mxgraph/javascript/dist/build.js

image

Another problem is that global variables are not declared, like mxLoadResources, mxForceIncludes, mxLoadStylesheets and mxResourceExtension.

I did the following steps:

  1. remove compilerOptions.types in tsconfig.app.json, this configuration will invalidate thetypeRoots in tsconfig.json

  2. delete src/app/mxgraph-engine/index.d.ts, (the reason for creating this file may be because the first step)

  3. declare global variables

    import factory from 'mxgraph';
    
    declare global {
      interface Window {
        mxBasePath: string;
        mxLoadResources: boolean;
        mxForceIncludes: boolean;
        mxLoadStylesheets: boolean;
        mxResourceExtension: string;
      }
    }
    
    window.mxBasePath = '../../assets/mxgraph';
    window.mxLoadResources = true;
    window.mxForceIncludes = false;
    window.mxLoadStylesheets = true;
    window.mxResourceExtension = '.txt';
    
    export default factory.call(window, {
      // not working see https://github.com/jgraph/mxgraph/issues/479
      mxBasePath: '../../assets/mxgraph',
    });

I will note the final solution to the sub-problem.
This is a bug of mxgraph, but since this library is currently unmaintained, there is a good chance that there is no perfect solution.

@Dhawaldeep An alternative is maxGraph/maxGraph in development, you can follow this repository.

Hi
I have been able to make the Angular 13 repository work with the guidance provided by @hungtcs in #50 (comment).

I suggest we update the README file and the examples. This would prevent users creating issue like this one in the future.
My suggestions:

  • declare the mxgraph globals in the Window interface
  • do not pass any options to the factory function as it generates issues. Defining the options globally work (mxGraph uses the globals): this is the way it is configured in the rollup example and I have successfully tested it with the Angular 13 repository

I have already proposed a PR for the rollup example: typed-mxgraph/typed-mxgraph-example-bundled-with-rollup#5.
I can also do it for the typed-mxgraph repository and the webpack example.

Additional Information
I have noticed that depending on the bundler or the build tool, some extra mxGraph globals are required to be set. The webpack example currently only define s mxBasePath, but in the rollup example, several are required. They seem to be required as well in the Angular 13 test repository.