Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

jsvectormap does not work in Angular #75

Closed
smoelker opened this issue Mar 22, 2022 · 1 comment
Closed

jsvectormap does not work in Angular #75

smoelker opened this issue Mar 22, 2022 · 1 comment

Comments

@smoelker
Copy link
Contributor

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.

smoelker added a commit to smoelker/jsvectormap that referenced this issue Mar 22, 2022
@themustafaomar
Copy link
Owner

Thank you!

You've just fixed another two issues at:

// Initialize the map
init(selector) {
const options = this.params
// @TODO: We can get the selector from params `this.params.selector` but unfortunately
// when passing a DOM element to jsVectorMap constructor, the DOM element doesn't get merged
// with defaults during merging the options so we need to get the selector directly from the options.
this.container = getElement(selector)

And https://github.com/themustafaomar/vuevectormap/blob/e74a7b509380ed4f7aaaa38444163e96c96e06f4/src/js/component.js#L33-L40

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants