ember-cli-chart icon indicating copy to clipboard operation
ember-cli-chart copied to clipboard

Get the chart instance

Open hy0ug0 opened this issue 8 years ago • 8 comments
trafficstars

I try to get the Chart instance to be able to use the getElementAtEvent() method. I have this :

onClick: (event, chartElements) => {
        this.handleChartClick(event, chartElements);
      }

And I want to access my Chart instance in my handleChartClickmethod, how can I do that ? The final purpose is to listen on click in axis labels and get their value.

hy0ug0 avatar Aug 04 '17 14:08 hy0ug0

I have exactly the same problem, would be great to have access to the Chart instance.

hkfrei avatar Aug 08 '17 09:08 hkfrei

If you EmberChart.extend you can then this.get('chart') -- or am I misunderstanding the problem?

aomran avatar Aug 16 '17 21:08 aomran

Let's say I have a component with this template {{ember-chart type='horizontalBar' data=barData options=chartOptions width=200 height=200}}

Now in my component.js I want to access the instance of the chart I created in my template, how I would do that ?

Same question apply if I have multiple charts in my template like that

{{ember-chart type='horizontalBar' data=barData options=chartOptions width=200 height=200}}
{{ember-chart type='horizontalBar' data=barData options=chartOptions width=200 height=200}}

How I can access each instance ?

Hoping I'm clear enough...

hy0ug0 avatar Aug 17 '17 13:08 hy0ug0

I assume you want the instance of the chart to react to some kind of event. You can extend this component.

// file: your-app/components/ember-chart.js

import EmberChart from 'ember-cli-chart/components/ember-chart';

export default EmberChart.extend({
  doubleClick() {
    alert("DoubleClickableComponent was clicked!");
   // this.get('chart') should give you the Chartjs instance.
  }
});

See ember component event handlers here: https://guides.emberjs.com/v2.14.0/components/handling-events/#toc_event-names

@Hugo-Contreras does this help?

aomran avatar Aug 26 '17 00:08 aomran

I was trying to handle an event on the Chart y-axis, so I did something like that (which is a bit ugly but working for now):

@readOnly
@computed('data')
  chartOptions () {
    const componentContext = this;
    return {
      maintainAspectRatio: false,
      onClick: function (event) {
        componentContext.handleChartClick(event, this);
      }
  }

And in my component I have this method to handle the click:

handleChartClick (event, chartInstance) {
    const helpers = Chart.helpers;
    const eventPosition = helpers.getRelativePosition(event, chartInstance.chart);
    const clickY = chartInstance.chart.scales['y-axis-0'].getValueForPixel(eventPosition.y);
    const rangeValues = this.get('data.barLabels')[clickY].split('-').map((value) => {
      return parseInt(value.trim(), 10);
    });

Thank's for your answer ! Might help at some point.

hy0ug0 avatar Aug 30 '17 12:08 hy0ug0

Would be great to have access to the chart instance without extending the component. This seems to be fairly straightforward in the unwrapped library.

My need arises not from event handling, but from using callbacks. I'm creating a custom tick callback for timezone handling. I must reference the displayFormats settings in my callback, ergo I need access to the xAxes object as a whole so I can reference the previously defined property.

For now, I am using the hack above (thanks, Hugo!) but would be cool to have something baked in that's a little less messy.

ghost avatar Aug 01 '19 18:08 ghost

Thanks @hy0ug0 I have used something similar in my component that has an <EmberChart /> where the calling template has an @onclick={{action "chartClicked"}} argument.

constructor() {
  const self = this; 

  const chartOptions = {
      onClick(e, context) {
        self.handleClickEvent(e, context, self, this);
      }
  };
}

handleClickEvent(e, context, self, chartInstance) {
  self = self || this;

  if ( chartInstance ) {
    const activePoints = chartInstance.getElementAtEvent(e);
    if ( activePoints.length > 0 ) {
      const chartElement = activePoints[0];
      const datapoint = chartInstance.config.data.datasets[chartElement._datasetIndex].data[chartElement._index];
      // Actions up
      self.args.onclick(datapoint);
    }
  }
}

queenvictoria avatar Apr 26 '20 02:04 queenvictoria

I was able to have acces to the instance through another ugly hack

<EmberChart
        @type="line"
        @data={{@model.data}}
        @chart={{@model.chart}}
        @options={{@model.options}}
></EmberChart>

It works even though it definitely is not clean

LaSylv avatar Apr 26 '20 09:04 LaSylv