I am using the latest version of Angular 2, V4.0.0 and I want to use graphs from the Chart.js library in my project without many complications.
How can I implement Chart.js in my angular project that does not give me problems in the final production?
You can implement Chart.js in a simple way with the following instructions:
1. Create a new project with angular-cli, skip if you already have one created
ng new example-chartjs
2. Install Chart.js in your project
npm install chart.js --save
3. Import Chart into its component
import Chart from 'chart.js';
4. Use Chart in your view and component
In your view:
<canvas id="myChart" width="400" height="400"></canvas>
In your component:
ngOnInit() {
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {...});
}
The component should look similar to the following
import { Component, OnInit } from '@angular/core';
import Chart from 'chart.js';
@Component({
selector: 'app-chart',
templateUrl: './chart.component.html'
})
export class DashboardComponent implements OnInit {
constructor() { }
ngOnInit() {
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {....});
}
}
Another alternative to use is to include the library from the file ".angular-cli.json"
1. Include in the scripts the library
"styles": [
"styles.css"
],
"scripts": [
"../node_modules/jquery/dist/jquery.min.js",
"../node_modules/chart.js/dist/Chart.min.js"
]
2. Declare a variable of type "any" in the controller
declare var Chart:any;
3. Use Chart in your view and component
In your view:
<canvas id="myChart" width="400" height="400"></canvas>
In your component:
ngOnInit() {
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {...});
}
The component should look similar to the following
import { Component, OnInit } from '@angular/core';
declare var Chart:any;
@Component({
selector: 'app-chart',
templateUrl: './chart.component.html'
})
export class DashboardComponent implements OnInit {
constructor() { }
ngOnInit() {
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {....});
}
}
First
npm install chart.js --save
Second
npm install @types/chart.js --save
Third - import Chart into component this way
import * as Chart from 'chart.js';
I've implemented the Chart.js on Angular at this way(first you'll need to install it using npm install chart.js --save
):
The folder structure of my project
src/
assets/
app/
charjs/
services/
First I've created a service called report.service.ts
:
src/app/services/report.service.ts
import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import 'rxjs/add/operator/map';
@Injectable()
export class ReportService {
constructor(public http: Http) {
}
getReports() {
return this.http.get('assets/report.json')
.map(res => res.json());
}
}
This service it's created based on Angular tutorial showing how to get a external file(or link) and retriece a Json data.
This is important to collect the data from external source(if you must)
The difference between a service and a component, It's you need to to insert this service as a provider on the app.module.ts :
src/app/app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { HttpModule, JsonpModule } from '@angular/http';
import { ReportService } from './services/report.service';
import { ChartjsComponent } from './chartjs/chartjs.component';
@NgModule({
declarations: [
AppComponent,
ChartjsComponent
],
imports: [
BrowserModule,
HttpModule,
JsonpModule
],
providers: [ReportService],
bootstrap: [AppComponent]
})
export class AppModule { }
After that I've created the component chartjs.component.js , and used AfterViewInit instead of OnInit. I've user this approach because our service retrieve the data in a asynchronous way and, because of that, the data might be provided before the view has been initiated.
src/app/chartjs/chartjs.component.ts
import { Component, AfterViewInit,ViewChild, ElementRef } from '@angular/core';
import Chart from 'chart.js';
import { Respon2se } from '@angular/http';
import 'rxjs/add/operator/map';
import { ReportService } from '../services/report.service';
@Component({
selector: 'app-chartjs',
templateUrl: './chartjs.component.html',
styleUrls: ['./chartjs.component.css']
})
export class ChartjsComponent implements AfterViewInit {
@ViewChild('graphcanvas') mycanvas:ElementRef;
createData;
chartOptions;
constructor(public reportService: ReportService) {
}
ngAfterViewInit() {
this.reportService.getReports().subscribe(reportsData => {
this.createData = {
labels: 'Scatter Dataset',
datasets: [{
label: "reportRetrieve",
data: reportsData,
}]
};
this.chartOptions = {
legend: {
display: false,
position: 'top',
labels: {
boxWidth: 80,
fontColor: 'black'
}
},
scales: {
xAxes: [{
gridLines: {
display: false,
color: "black"
},
scaleLabel: {
display: true,
labelString: "Report Size",
fontColor: "red"
}
}],
yAxes: [{
gridLines: {
color: "black",
display: false
},
scaleLabel: {
display: true,
labelString: "Chart Report",
fontColor: "green"
}
}]
},
layout: {
padding: {
left: 0,
right: 50,
top: 50,
bottom: 0
}
},
maintainAspectRatio: false
};
let ctx = this.mycanvas.nativeElement.getContext('2d');
new Chart(ctx, {
type: 'bubble',
data: this.createData,
options: this.chartOptions,
responsive: false
});
});
}
}
A few comments about this file;
. After imported the service, I've used subscribe,to allow charjs library to get the data and push it on new Chart
. ChartOptions its just a variable to change the chart view the way you want, I've used to create a bubble chart.
. You can define if it's responsive or not.
After you've done that, you'll need to set your html:
src/app/chartjs/chartjs.component.html
<div style="height: 600px;width: 600px">
<canvas #graphcanvas></canvas>
</div>
I hope that helps someone who couldn't implement on the other ways.
I believe, on Angular, chartjs will work like below, because context is available afterViewInit() not onInit()
import { Component, ViewChild, ElementRef, AfterViewInit} from '@angular/core';
import Chart from 'chart.js';
@Component({
selector: 'app-statistics',
templateUrl: './statistics.component.html',
styleUrls: ['./statistics.component.css']
})
export class StatisticsComponent implements AfterViewInit{
@ViewChild('myChart') Chart: ElementRef;
constructor() {
}
ngAfterViewInit() {
var ctx = this.Chart.nativeElement.getContext('2d')
var myChart = new Chart(ctx,{...})
}
}