kurkle / chartjs-chart-treemap

Chart.js module for creating treemap charts
MIT License
140 stars 34 forks source link

undefined error firing while hovering the chart #88

Closed koin612 closed 2 years ago

koin612 commented 2 years ago

I'm using chart.js 3.7.1 and chartjs-chart-treemap 2.0.2 in an vue project. The chart renders but when I hover it does not show the tooltip and fires errors in console. Sometimes it worked when the live-server reloaded code and when I've did the imports in main.ts and in the component itself.

chart.esm.js?9b4a:9037 Uncaught TypeError: Cannot read properties of undefined (reading 'call')
    at Tooltip._positionChanged (chart.esm.js?9b4a:9037:1)
    at Tooltip.handleEvent (chart.esm.js?9b4a:9007:1)
    at Object.afterEvent (chart.esm.js?9b4a:9077:1)
    at callback (helpers.segment.js?dd3d:92:1)
    at PluginService._notify (chart.esm.js?9b4a:4922:1)
    at PluginService.notify (chart.esm.js?9b4a:4909:1)
    at Chart.notifyPlugins (chart.esm.js?9b4a:6047:1)
    at Chart._eventHandler (chart.esm.js?9b4a:6074:1)
    at listener (chart.esm.js?9b4a:5952:1)
    at Chart.event (chart.esm.js?9b4a:3214:1)

the component looks like this

<template>
  <canvas ref="canvas" />
</template>

<script lang="ts">
import { Vue, Component, Ref } from "vue-property-decorator";
import { Chart } from "chart.js";
import { TreemapController, TreemapElement } from "chartjs-chart-treemap";
Chart.register(TreemapController, TreemapElement);

@Component
export default class TreemapChart extends Vue {
  @Ref("canvas") canvas!: HTMLCanvasElement;

  ctx2d = null as any;

  mounted(): void {
    this.ctx2d = this.canvas.getContext("2d");
    new Chart(this.ctx2d!, {
      type: "treemap",
      data: {
        datasets: [
          {
            label: "Basic treemap",
            tree: [15, 6, 6, 5, 4, 3, 2, 2],
            spacing: 0.1,
            borderWidth: 2,
            borderColor: "rgba(180,180,180, 0.15)",
          },
        ],
      },
      options: {
        responsive: true,
        maintainAspectRatio: false,
        plugins: {
          title: {
            display: true,
            text: "Basic treemap example",
          },
          legend: {
            display: false,
          },
        },
      },
    } as any);
  }
}
</script>
kurkle commented 2 years ago

Maybe you could try importing and registering Tooltip?

Edit: just to make it clear, the top part:

import { Vue, Component, Ref } from "vue-property-decorator";
import { Chart, Tooltip } from "chart.js";
import { TreemapController, TreemapElement } from "chartjs-chart-treemap";
Chart.register(Tooltip, TreemapController, TreemapElement);
kurkle commented 2 years ago

Also, if a the "Basic treemap example" text is rendered on the chart, I suspect this might be an issue with SSR. You could try disabling that for this component (don't as me how, I don't use Vue).

koin612 commented 2 years ago

ty for your help. It's client side rendered but the tooltip (I've tried already) import seems like it's working now. I've already imported in main.ts the registerables like:

import { Chart, registerables } from "chart.js";
import { TreemapController, TreemapElement } from "chartjs-chart-treemap";
Chart.register(TreemapController, TreemapElement, ...registerables);

which I think should import Tooltip and don't treeshake. Specifying it explicitly again/twice seems to work from my tests.

kurkle commented 2 years ago

I've usually created a file for doing the registration like:

chart.js

import { Chart, registerables } from "chart.js";
import { TreemapController, TreemapElement } from "chartjs-chart-treemap";
Chart.register(...registerables, TreemapController, TreemapElement);

export default Chart;

component.js

import Chart from './chart';
...

But the actual fix is probably registering the ...registrables before TreemapController: Chart.register(...registerables, TreemapController, TreemapElement);

kurkle commented 2 years ago

And the explanation is here, if Tooltip is not registered before TreemapController, the tooltip positioner is not registered.

https://github.com/kurkle/chartjs-chart-treemap/blob/971f84b935d994dee2ec7ab0c41d2b52a7f46d16/src/controller.js#L372-L386

Should probably emit a warning about this.

koin612 commented 2 years ago

thank you kurkle for analyzing the problem, really appreciate this. I can confirm if I do Chart.register(...registerables, TreemapController, TreemapElement) it works as intended. Kinda makes sense, but I did not expect an order in the register at first glance. Seeing the controller it makes sense.