Search code examples
javascriptangularjhipstertypescript-typingsmetronic

Including custom typings in JHipster (v5.82) project


The basic idea is to start with a new JHipster project (v5.8.2) and integrate the Metronic Angular theme in it. I haven't found much in the way of documentation for this task, but sluggishly I've integrated the various css/js bundles, the components, however I ran across a problem with some of their directives. So basically in toggle.directive.ts after the view initiates it tries to create a new KTToggle see

ngAfterViewInit(): void {
    this.toggle = new KTToggle(this.el.nativeElement, this.options);
}

KTToggle is defined in scripts.bundle.js that I've already imported in vendor.ts. I've also copied typings.d.ts file from metronic in src/main/webapp/app.

The problem is that it doesn't find KTToggle, when running npm run webpack:build I get no error, but when actually trying to access the page I get

ERROR ReferenceError: "KTToggle is not defined"

Additionally in IntelliJ I get the following error

TS2350: Only a void function can be called with the 'new' keyword

I tried to declare KTToggle straight in the directive

declare var KTToggle: any;

But this give me the same ReferenceError. Also in tsconfig.json I tried to point to the typings file through typeRoots, types, files all gave me either the same error or for types caused other parts of the app to fail.

I'm not too experienced with Angular/Webpack but I suspect the typing is not properly loaded, because if I try to go to the definition of KTToggle in IntelliJ it points me to the scripts.bundle.js file.

I welcome any kind of help, thank you.

Additional info:

typings.d.ts

    /* SystemJS module definition */
declare var module: NodeModule;
interface NodeModule {
    id: string;
}

declare var KTMenu: any;
declare var KTOffcanvas: any;
declare var KTScrolltop: any;
declare var KTHeader: any;
declare var KTToggle: any;
declare var KTUtil: any;
declare var KTPortlet: any;
declare var KTDialog: any;
declare var Chart: any;

scripts.bundle.js

.....    
KTToggle=function(t,e){var n=this,i=KTUtil.get(t);KTUtil.get("body");if(i){var o={togglerState:"",targetState:""}
....

L.E. 2020-04-11 What we ended up doing was setting a new entry point in the the webpack configuration file (both dev and prod), like this:

    entry: {
        global: './src/main/webapp/content/scss/global.scss',
        main: './src/main/webapp/app/app.main',
        // metronic scripts bundled, contains needed JS for Metronic functionalities
        metronicScripts: [
            './src/main/webapp/content/metronic/assets/demo/default/base/scripts.bundle.js'
        ]
    },

and then in the common webpack configuration we modified the HtmlWebpackPlugin to include the new chunk like so:

new HtmlWebpackPlugin({
            template: './src/main/webapp/index.html',
            chunks: [
                // include metronic bundle before the main bundle so that we can utilize metronic variables in components and initialize the layout for example
                'metronicScripts'
                ,'polyfills'
                ,'main'
                ,'global'
            ],
            chunksSortMode: 'manual',
            inject: 'body'
        }),

Afterwards we could use the various elements from metronic inside components like so

...
declar var KTUtil: any;

@Component({...})
...
ngOnInit() {
   KTUtil.init();
}

Solution

  • (ERROR ReferenceError: "KTToggle is not defined") mean you not load the script file toggle.js,

    So make sure you load all what Metronic loaded in index.html file and not delete imports of it, by default Metronic load this files in index.html :

    <script src="assets/js/global/components/base/util.js" type="application/javascript"></script>
    <script src="assets/js/global/components/base/header.js" type="application/javascript"></script>
    <script src="assets/js/global/components/base/menu.js" type="application/javascript"></script>
    <script src="assets/js/global/components/base/offcanvas.js" type="application/javascript"></script>
    <script src="assets/js/global/components/base/scrolltop.js" type="application/javascript"></script>
    <script src="assets/js/global/components/base/toggle.js" type="application/javascript"></script>
    <script src="assets/js/global/components/base/dialog.js" type="application/javascript"></script>
    <script src="assets/js/global/components/base/wizard.js" type="application/javascript"></script>