Skip to content

jsvectormap does not work in Angular #75

@smoelker

Description

@smoelker

Loading jsvectormap in an Angular component does not work. The proper way to get a reference to the container element is to use the @ViewChild annotation and then load the map on ngAfterViewInit. Doing so causes a stack overflow (InternalError: too much recursion).

Steps to reproduce:

ng new
npm install jsvectormap

package.json

{
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "watch": "ng build --watch --configuration development",
    "test": "ng test"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "~13.1.0",
    "@angular/common": "~13.1.0",
    "@angular/compiler": "~13.1.0",
    "@angular/core": "~13.1.0",
    "@angular/forms": "~13.1.0",
    "@angular/platform-browser": "~13.1.0",
    "@angular/platform-browser-dynamic": "~13.1.0",
    "@angular/router": "~13.1.0",
    "jsvectormap": "^1.4.5",
    "rxjs": "~7.4.0",
    "tslib": "^2.3.0",
    "zone.js": "~0.11.4"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "~13.1.2",
    "@angular/cli": "~13.1.2",
    "@angular/compiler-cli": "~13.1.0",
    "@types/jasmine": "~3.10.0",
    "@types/node": "^12.11.1",
    "jasmine-core": "~3.10.0",
    "karma": "~6.3.0",
    "karma-chrome-launcher": "~3.1.0",
    "karma-coverage": "~2.1.0",
    "karma-jasmine": "~4.0.0",
    "karma-jasmine-html-reporter": "~1.7.0",
    "typescript": "~4.5.2"
  }
}

app.component.html

<div #map></div>

app.component.ts

import {AfterViewInit, Component, ElementRef, ViewChild} from '@angular/core';
// @ts-ignore
import jsVectorMap from "jsvectormap";

import "jsvectormap/src/maps/world"

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent implements AfterViewInit {

  @ViewChild('map')
  private mapRef!: ElementRef<HTMLDivElement>;

  ngAfterViewInit(): void {

    new jsVectorMap({
      selector: this.mapRef.nativeElement,
    });

  }
}

Error in FireFox:

ERROR InternalError: too much recursion
    toString zone.js:1571
    t jsvectormap.min.js:1
    t jsvectormap.min.js:1
    r jsvectormap.min.js:1
    o jsvectormap.min.js:1
    i jsvectormap.min.js:1
    s jsvectormap.min.js:1
    s jsvectormap.min.js:1
    o jsvectormap.min.js:1
    i jsvectormap.min.js:1
    r jsvectormap.min.js:1
    r jsvectormap.min.js:1
    o jsvectormap.min.js:1
    i jsvectormap.min.js:1
    s jsvectormap.min.js:1
    s jsvectormap.min.js:1
    o jsvectormap.min.js:1
    i jsvectormap.min.js:1
    r jsvectormap.min.js:1
    ...

Error in Chrome:

core.mjs:6461 ERROR RangeError: Maximum call stack size exceeded
    at TView.Object.toString (polyfills.js:5945:42)
    at vendor.js:938:1000
    at Object.t [as isMergeableObject] (vendor.js:938:1096)
    at i (vendor.js:938:1217)
    at vendor.js:938:1343
    at Array.map (<anonymous>)
    at Object.s [as arrayMerge] (vendor.js:938:1319)
    at o (vendor.js:938:2199)
    at i (vendor.js:938:1238)
    at vendor.js:938:1992

The error happens when merging the map's options. Specifically when iterating over the properties of the selector property which is, in this case, a HTMLDivElement. I suspect that the infinite recursion is due to the hierarchical nature of the DOM element (the DOM element holds a reference to it's parent and children which, in turn, hold a reference to their parent and children).

A solution would be to not merge the properties of DOM elements.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions