[SOLVED] Ionic 2 + NG2-Charts

Hello,

I was trying to use ng2-charts which is an Angular 2 directive for Charts.js

Back when I was using Ionic 1.2 … I used this directive and it worked completely fine with no issues.

Now with Ionic 2 + ng2-charts I am having this issue where the chart would not be displayed until I resize the screen. This issue only occurs on Ionic. If you try out the demo here, use developer tools to emulate an iPhone screen size, and refresh the page… Everything will work out fine.

I created a demo application that’s available to be viewed via this URL: http://cacoch.com/charttest/
Source code available here: https://github.com/ihadeed/charttest

Any thoughts? What could be causing this issue?

1 Like

The weird thing is it works as good as you are in IOS, i tried with some google nexus but the chart dissapeard, maybe it only works in ios for now? I didn’t know about this plugin, i’ll be making my research on this.

Relate to this issue: https://github.com/jtblin/angular-chart.js/issues/17

Seems to be dealing with the same issue as you, there’s some ideas, the one you should be trying is to set the chart only after the tab has been loaded.

According with your code, try setting up the data in the ngAfterContentInit() function or in ngAfterViewInit(), relate to: https://angular.io/docs/ts/latest/guide/cheatsheet.html in the section Directive and component change detection and lifecycle hooks

Maybe it worked fine on iOS because when you launched developer tools it resized the screen for you. On my end it doesn’t work on iOS or Android until screen is resized or flipped (basically the device-width has to change)

My bad, didn’t test properly, but the issues i linked could be the answer.

Wrapping it with ngAfterViewInit() {} didn’t work …

Didn’t think it would work, because if it was an issue with when the data is given, then the Randomize button should make the chart appear.

The only luck I’ve had to display the chart on init is to set the option responsive to false… but that doesn’t give me the size I desire.

Finally managed to fix it.

Had to edit the directive itself to fix the issue.

Line 124 in charts.ts is the ngOnInit() function for the component. In this function the developer calls refresh() that recreates the canvas according to current parent width/height. I just had to wrap that refresh function with a small delay.

Changed line 128 from this:
this.refresh()
to
setTimeout(()=>this.refresh(), 100);

1 Like

Kind of hacky? then send a pr to the github repo, if this does fix it then you should let the world have that fix :stuck_out_tongue:

I will test to ensure that it’s a permanent fix before sending a PR …
I tried making the timeout 50ms instead of 100ms and it didn’t work. So I’m afraid that the delay relies on how fast the page loads. Which means on slower devices this fix will not work unless the timeout is higher.

I got the whole idea by reading these lines here: 182 - 186 …

I’m just not sure what is the equivalent of elem[0].clientHeight and container.clientHeight … I tried watching the values of various elements of the Angular2 components but can’t seem to find any change in any width/height properties. Even ngOnChange() doesn’t detect anything.

Ok I improved the solution and posted a PR …

this.parent.clientHeight ended up being the equivalent to the code quoted in the previous quote. So I just used the statement if(this.options.responsive && this.parent.clientHeight === 0). One more tweak that must be done is setting the CSS of the parent (the directive) to disply: block

2 Likes

Hi @jhadeed i have this working since a while ago, but i haven’t been able to update to recent version because it breaks my app, have you had this kind of experience?

For the record, since I spent a day trying to figure this out, I’ll put this here in case anyone needs it:

I think I managed to make ng2-charts work correctly.

  • I installed ng2-charts and chart.js through npm
  • I used the setup described in the ng2-charts docs for html & typescript
  • I imported chart.js in my app.ts as follows:

import ‘…/node_modules/chart.js/dist/Chart.bundle.min.js’;

(this is what mainly made the difference in the end)

  • In the scss of the page that is displaying the chart, I added

.chart {
display: block;
height: 100%;
}

The charts now show up fine :smile:

1 Like

Yuck. You shouldn’t ever have to reference node_modules, and you generally don’t want to be including bundles (at least when bundling with webpack - I assume browserify also prefers module sources).

I don’t use ng2-charts, but my homebrew donut chart directive works just fine in Ionic with:

var Chart = require('chart.js/src/chart');

@Injectable()
@Component({
  selector: 'donut-chart',
  template: `<canvas #canvas [height]="height" [width]="width"></canvas>`
})
export class DonutChart implements AfterViewInit {
  @ViewChild('canvas') private _canvas:ElementRef;
  ngAfterViewInit():void {
    let chart = new Chart(this._canvas.nativeElement, {...});
  }
}

In my project i updated to latest with Ionic beta.8 and angular2-RC.1 and it works flawlessly, if any of you use webpack, it is very easy to set up.

rapropos, are there a few bits missing from your component? I got a full homebrew component far as this;

import {Injectable, Component, ViewChild, ElementRef, AfterViewInit} from '@angular/core';
import * as Chart from 'chart.js';

@Injectable()
@Component({
  selector: 'donut-chart',
  template: `<canvas #canvas [height]="height" [width]="width"></canvas>`
})
export class DonutChart implements AfterViewInit {
  @ViewChild('canvas') private _canvas:ElementRef;
  ngAfterViewInit():void {

    console.log(this._canvas.nativeElement);

    let chart = new Chart(this._canvas.nativeElement.getContext('2d'), {
      type: 'doughnut',
      data: {
        labels: ['yolo', 'dolo', 'solo'],
        datasets: [{
          data: [300, 50, 100],
            backgroundColor: [
                "#FF6384",
                "#36A2EB",
                "#FFCE56"
            ],
            hoverBackgroundColor: [
                "#FF6384",
                "#36A2EB",
                "#FFCE56"
            ]
        }]
      }
    });
  }
}

But I just get a canvas with zero height and zero width.

My entire component is here, but the key is turning responsive off. It’s bugged and will result in the zero width/height you are seeing.

Hey @rapropos check what I did here:
https://github.com/zyramedia/ng2-chartjs2/blob/master/components/chart.component.ts#L10

Setting :host {display: block} solved the issue that happens when you have responsive set to true.

1 Like

import ‘…/node_modules/chart.js/dist/Chart.bundle.min.js’; helped me … I was trying to include in index.html