wa0x6e / cal-heatmap

Cal-Heatmap is a javascript charting library to create a time-series calendar heatmap
http://cal-heatmap.com
MIT License
2.7k stars 292 forks source link

Cal-heatmap not working in Angular: Uncaught TypeError: Cannot read properties of undefined (reading 'document') #274

Closed tomaszs closed 1 year ago

tomaszs commented 2 years ago

I have installed cal-heatmap for an Angular project (v12). The project uses "d3": "^5.16.0". Use case:

"cal-heatmap": "^3.6.2",

import CalHeatMap from 'cal-heatmap';

ngOnInit() {
    const cal = new CalHeatMap();
    cal.init({
      itemSelector: '#calheatmap',
      domain: 'month',
      subDomain: 'day',
      cellSize: 20,
      subDomainTextFormat: '%d',
      range: 1,
      displayLegend: false,
    });
  }

constructor line throws:

Uncaught TypeError: Cannot read properties of undefined (reading 'document')
    at d3.js:8
    at Object.56645 (d3.js:9554)
    at __webpack_require__ (bootstrap:24)
    at fn (hot module replacement:61)
    at Object.56111 (cal-heatmap.min.js:8)
    at __webpack_require__ (bootstrap:24)
    at fn (hot module replacement:61)
    at Module.99607 (chart-bars.component.html:1)
    at __webpack_require__ (bootstrap:24)
    at fn (hot module replacement:61)

Expected result: no error Actual result: error

nitoloz commented 2 years ago

Same error for me with angular v13. @tomaszs did you find a solution for that? My package.json looks as follows:

 "dependencies": {
    "@angular/animations": "13.1.3",
    "@angular/cdk": "13.1.3",
    "@angular/common": "13.1.3",
    "@angular/compiler": "13.1.3",
    "@angular/core": "13.1.3",
    "@angular/forms": "13.1.3",
    "@angular/localize": "~13.1.3",
    "@angular/material": "13.1.3",
    "@angular/platform-browser": "13.1.3",
    "@angular/platform-browser-dynamic": "13.1.3",
    "@angular/platform-server": "13.1.3",
    "@angular/router": "13.1.3",
    "@angular/service-worker": "13.1.3",
    "@capacitor-community/barcode-scanner": "^2.0.0",
    "@capacitor/android": "^3.0.0",
    "@capacitor/app": "^1.0.0",
    "@capacitor/camera": "^1.0.1",
    "@capacitor/core": "^3.0.0",
    "@capacitor/filesystem": "^1.0.2",
    "@capacitor/haptics": "^1.0.2",
    "@capacitor/ios": "^3.0.0",
    "@capacitor/keyboard": "^1.0.2",
    "@capacitor/share": "^1.0.3",
    "@capacitor/status-bar": "^1.0.2",
    "@fullcalendar/angular": "5.10.1",
    "@fullcalendar/daygrid": "5.10.1",
    "@hapi/nes": "12.0.4",
    "@ionic-native/core": "^5.33.1",
    "@ionic-native/open-native-settings": "^5.33.1",
    "@ionic/angular": "^5.6.9",
    "@ionic/angular-toolkit": "^4.0.0",
    "@ngrx/effects": "13.0.2",
    "@ngrx/entity": "13.0.2",
    "@ngrx/router-store": "13.0.2",
    "@ngrx/store": "13.0.2",
    "@ngrx/store-devtools": "13.0.2",
    "@sgratzl/chartjs-chart-boxplot": "3.6.0",
    "@types/chart.js": "2.9.35",
    "@types/fabric": "1.5.54",
    "@ungap/global-this": "^0.4.4",
    "@zxing/browser": "0.0.7",
    "@zxing/library": "^0.18.3",
    "@zxing/ngx-scanner": "3.2.0",
    "ag-grid-angular": "26.2.0",
    "ag-grid-community": "26.2.0",
    "angular-oauth2-oidc": "12.0.0",
    "angular2-signaturepad": "2.11.0",
    "babel-preset-es2015": "^6.24.1",
    "cal-heatmap": "3.6.2",
    "chart.js": "3.6.2",
    "chartjs-adapter-moment": "1.0.0",
    "cordova-open-native-settings": "^1.5.5",
    "core-js": "3.11.2",
    "d3": "6.7.0",
    "date-fns": "2.28.0",
    "date-fns-tz": "1.1.4",
    "dotenv-webpack": "^7.0.3",
    "dragula": "3.7.3",
    "fabric": "1.7.22",
    "fuse.js": "3.4.5",
    "idb": "2.1.3",
    "js-cookie": "2.2.1",
    "linkifyjs": "2.1.9",
    "lodash": "4.17.21",
    "lodash.intersection": "4.4.0",
    "lodash.sortby": "4.7.0",
    "material-design-icons": "3.0.1",
    "moment": "2.29.1",
    "ng2-dragula": "1.5.0",
    "ng2-file-upload": "1.4.0",
    "ngx-extended-pdf-viewer": "9.0.5",
    "ngx-perfect-scrollbar": "10.1.0",
    "panzoom": "4.5.0",
    "posthog-js": "1.12.1",
    "qrcode": "1.4.4",
    "roboto-fontface": "0.10.0",
    "rrule": "2.6.8",
    "rxjs": "7.5.2",
    "sass-loader": "11.1.1",
    "ts-helpers": "1.1.2",
    "tslib": "2.3.1",
    "typescript": "4.5.5",
    "zone.js": "~0.11.4"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "~13.1.4",
    "@angular-eslint/builder": "13.0.1",
    "@angular-eslint/eslint-plugin": "13.0.1",
    "@angular-eslint/eslint-plugin-template": "13.0.1",
    "@angular-eslint/schematics": "13.0.1",
    "@angular-eslint/template-parser": "13.0.1",
    "@angular/cli": "13.1.4",
    "@angular/compiler-cli": "13.1.3",
    "@babel/core": "7.13.16",
    "@capacitor/cli": "^3.0.0",
    "@storybook/addon-actions": "^6.3.10",
    "@storybook/addon-docs": "^6.3.10",
    "@storybook/addon-essentials": "^6.3.10",
    "@storybook/addon-links": "^6.3.10",
    "@storybook/addons": "6.3.10",
    "@storybook/angular": "^6.3.10",
    "@storybook/builder-webpack5": "^6.3.10",
    "@storybook/manager-webpack5": "^6.3.10",
    "@types/cal-heatmap": "3.5.35",
    "@types/d3": "6.3.0",
    "@types/hapi__nes": "11.0.5",
    "@types/jasmine": "3.6.9",
    "@types/js-cookie": "2.2.6",
    "@types/linkifyjs": "2.1.4",
    "@types/lodash": "4.14.168",
    "@types/node": "14.14.41",
    "@types/qrcode": "1.4.0",
    "@typescript-eslint/eslint-plugin": "5.10.0",
    "@typescript-eslint/parser": "5.10.0",
    "babel-loader": "8.2.2",
    "concurrently": "6.0.2",
    "cypress": "9.3.1",
    "eslint": "8.7.0",
    "eslint-config-prettier": "8.3.0",
    "eslint-plugin-jasmine": "4.1.3",
    "eslint-plugin-jsdoc": "37.6.3",
    "eslint-plugin-prettier": "4.0.0",
    "eslint-plugin-rxjs": "5.0.1",
    "fast-check": "2.14.0",
    "http-proxy": " 1.18.1",
    "http-server": "0.12.3",
    "husky": "7.0.2",
    "jasmine-core": "4.0.0",
    "jasmine-marbles": "0.9.1",
    "jasmine-spec-reporter": "7.0.0",
    "karma": "6.3.2",
    "karma-chrome-launcher": "3.1.0",
    "karma-cli": "2.0.0",
    "karma-jasmine": "4.0.1",
    "karma-jasmine-diff-reporter": "2.0.1",
    "karma-remap-istanbul": "0.6.0",
    "karma-sourcemap-loader": "0.3.8",
    "karma-webpack": "5.0.0",
    "lint-staged": "11.1.2",
    "native-run": "^1.4.0",
    "ngx-i18nsupport": "0.17.1",
    "prettier": "2.5.1",
    "storybook-zeplin": "1.3.1",
    "ts-node": "10.4.0",
    "tsconfig-paths-webpack-plugin": "^3.5.1"
  }
tomaszs commented 2 years ago

No didn't get any answer so far

nitoloz commented 2 years ago

According to the issues I've found (plotly1, plotly2, and SO) it seems that problem is with angular bundling cal-heatmap into es2015 module which breaks the app

alan-agius4 commented 2 years ago

Cross posted from https://github.com/angular/angular-cli/issues/22588 for visibility.

The issue here is that type=module forces JavaScript to run in strict mode. This means that it's no longer possible to reference the document object through this, which the version of d3 being used is dependent on. More information about this can be found: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode#securing_javascript.

What you can do is to add both d3 and cal-heatmap as global scripts and use the CalHeatMap as a global object.

This can be done by using the browser builder scripts option.

"scripts": [
  "node_modules/d3/d3.js",
  "node_modules/cal-heatmap/cal-heatmap.js"
]
const CalHeatMap = (globalThis as any)['CalHeatMap'];
console.log(CalHeatMap);

That said, I strongly recommand that you look for an alternative library, as it seems that cal-heatmap is not maintained and therefore I doubt it will continue to evolve to made compliant with the latest JavaScript versions and standards.

tomaszs commented 2 years ago

Thanks!

wa0x6e commented 1 year ago

import CalHeatMap from 'cal-heatmap'; is indeed not working, as the tool is not using ES6 standard.

v4 will fix that, it's a full refactoring, to es6 classes and all the new tech

jaisahni commented 1 year ago

I am using the newer version v4 of cal-heatmap and get this error with my angular 11 project on compile : Module not found: Error: Can't resolve 'cal-heatmap' in .... I am importing it like so : import CalHeatmap from 'cal-heatmap';