4

I'm using LeafletJS library in Angular 2 application. The library itself is working fine since I've included the type definition (leaflet.d.ts) and of course the leaflet node module.

I'm trying to import a plugin for the leaflet library called "leaflet-canvasicon" and there is no available type definition for it and since it's written in ES5 whenever I try to include it, the compiler is satisfied, yet I recieve the following error at the console:

leaflet-src.js:314
Uncaught TypeError: this.callInitHooks is not a function
    at Object.NewClass (http://localhost:2080/main.bundle.js:58716:8)
    at http://localhost:2080/main.bundle.js:77650:180
    at Object.<anonymous> (http://localhost:2080/main.bundle.js:77652:3)
    at __webpack_require__ (http://localhost:2080/inline.js:53:30)
    at Object.<anonymous> (http://localhost:2080/main.bundle.js:54476:18)
    at __webpack_require__ (http://localhost:2080/inline.js:53:30)
    at Object.<anonymous> (http://localhost:2080/main.bundle.js:54411:90)
    at __webpack_require__ (http://localhost:2080/inline.js:53:30)
    at Object.<anonymous> (http://localhost:2080/main.bundle.js:54600:70)
    at __webpack_require__ (http://localhost:2080/inline.js:53:30)

I thought of many solutions:

  • Make a new type definition for the plugin (leaflet-canvasicon.d.ts) and use the namespace declaration merging feature in Typescript in order to still use the plugin as L.CanvasIcon

  • Rewrite the plugin using typescript extending the existing interfaces in namespace L.

  • Stop using the typed 'leaflet' and just import the node module written in ES5 then add L declaration in angular's typings.d.ts file: declare var L: any;

But every time I face compiler issues. I think I'm doing it wrong. How can I include the plugin, keep the compiler satisfied and be able to use it as L.CanvasIcon

Here is package.json file:

 "dependencies": {
        "@angular/common": "2.1.2",
        "@angular/compiler": "2.1.2",
        "@angular/compiler-cli": "2.1.2",
        "@angular/core": "2.1.2",
        "@angular/forms": "2.1.2",
        "@angular/http": "2.1.2",
        "@angular/platform-browser": "2.1.2",
        "@angular/platform-browser-dynamic": "2.1.2",
        "@angular/platform-server": "2.1.2",
        "@angular/router": "3.1.2",
        "@types/leaflet": "^1.0.36",
        "core-js": "^2.4.1",
        "leaflet": "^1.0.1",
        "leaflet-canvasicon": "^0.1.6",
        "leafletjs-canvas-overlay": "^1.0.1",
        "rxjs": "5.0.0-rc.1",
        "ts-helpers": "^1.1.2",
        "zone.js": "^0.6.26"
      },
      "devDependencies": {
        "angular-cli": "1.0.0-beta.19-3",
        "ts-node": "1.6.1",
        "tslint": "3.15.1",
        "typescript": "2.0.6",
        "typings": "^1.5.0"
      }
    }

2 Answers 2

2

This is runtime error not related to missing typings. The problem is related to leaflet version mismatch.

It seems that leaflet-canvasicon is designed for older versions of leaflet. Try to fallback to leaflet with version 0.7.x.

 "dependencies": {
        "@angular/common": "2.1.2",
        "@angular/compiler": "2.1.2",
        "@angular/compiler-cli": "2.1.2",
        "@angular/core": "2.1.2",
        "@angular/forms": "2.1.2",
        "@angular/http": "2.1.2",
        "@angular/platform-browser": "2.1.2",
        "@angular/platform-browser-dynamic": "2.1.2",
        "@angular/platform-server": "2.1.2",
        "@angular/router": "3.1.2",
        "@types/leaflet": "0.7.x",
        "core-js": "^2.4.1",
        "leaflet": "0.7.x", // note the change
        "leaflet-canvasicon": "^0.1.6",
        "leafletjs-canvas-overlay": "^1.0.1",
        "rxjs": "5.0.0-rc.1",
        "ts-helpers": "^1.1.2",
        "zone.js": "^0.6.26"
      },
      "devDependencies": {
        "angular-cli": "1.0.0-beta.19-3",
        "ts-node": "1.6.1",
        "tslint": "3.15.1",
        "typescript": "2.0.6",
        "typings": "^1.5.0"
      }
    }

For the future, you can remember that this.callInitHooks is not a function is typical problem after loading old extensions to leaflet version >=1

Sign up to request clarification or add additional context in comments.

2 Comments

yes, it works after falling back to leaflet 0.7 version. yet type definition is still needed to use it within the same namespace as L.CanvasIcon.
How did you manage the type definition needed for using the plugin?
1

Import this file after leaflet if you need to use leaflet plugins in typescript.

declare module L {
    // plugins that extend Class i.e L.MyClass
    export let MyClass:any;
    // plugins that uses class factory i.e myClass
    export let myClass:any;

   //plugins that extend Control comes here i.e L.Control.Navbar
   export namespace Control {
      export let Navbar: any;
   }
   // plugins that have control factories come here i.e. L.control.navbar
  export namespace control {
     export let navbar: any;
  }

  //plugins that extend Layer comes here i.e L.Layer.NewLayer
   export namespace Layer {
      export let NewLayer: any;
   }
  // plugins that have layer factories come here i.e. L.layer.newLayer
  export namespace layer {
     export let newLayer: any;
  }
  //plugins that extend Handler comes here i.e. L.Handler.NewHandler
   export namespace Handler {
      export let NewHandler: any;
   }
  // plugins that have handler factories come here i.e. L.Handler.newHandler
  export namespace handler {
     export let newHandler: any;
  }
}

You can be explicit with the types if you want to.

1 Comment

Hello, what do you do if you get an error that complains like "typeerror: L.Control.LinearCore is not a constructor"? I've added your code with my variable names, but is there another bit that is needed if my plugin expects a constructor?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.