C3.js in Angular2 getting error - javascript

I am trying to use c3.js in an angular 2 project and I keep getting the same error:
AppComponent.html:5 ERROR TypeError: Cannot read property 'id' of undefined
at Object.eval [as updateRenderer] (ng:///AppModule/AppComponent.ngfactory.js:39:29)
...
No compilation errors.
index.html:
<!-- CSS for C3 -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.12/c3.css" rel="stylesheet" type="text/css">
<!-- Load d3.js-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.9.1/d3.min.js" charset="utf-8"></script>
<!-- Load c3.js-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.12/c3.js"></script>
app.module.ts:
... (beginning of the file)
import { RcpChartComponent } from './chart.component';
#NgModule({
declarations: [
AppComponent,
RcpChartComponent
... (end of the file)
app.component.ts:
import { Component, OnInit } from '#angular/core';
import { RcpChart } from './chart.component';
import { RcpChartDataService } from './data.service';
#Component({
selector: 'app-root',
providers: [RcpChartDataService],
template: `
<h1>My Title</h1>
<div>Chart:</div>
<div>
<rcpchart style="text-align:center; height:700px; width:700px"[id]="chart.id"></rcpchart>
`
})
export class AppComponent implements OnInit{
title = 'My Title';
chart: RcpChart;
constructor(private rcpChartDataService: RcpChartDataService) { }
getCharts(): void {
this.rcpChartDataService.getChartData().then(charts => this.chart = charts);
}
ngOnInit(): void {
this.getCharts();
}
}
configuration.chart.ts:
import { RcpChart } from "./chart.component";
export const CHARTS: RcpChart[] = [
{
id: "line",
name: "A vs B",
type: "line"
}
];
data.service.ts:
import { Injectable } from '#angular/core';
import { CHARTS } from './configuration.chart';
import {RcpChart} from "./chart.component";
#Injectable()
export class RcpChartDataService {
getChartData(): Promise<any> {
return Promise.resolve(CHARTS);
}
}
and the famous chart component now,
chart.component.ts:
import {Component, Input, Output, EventEmitter, OnInit, AfterViewInit,
ChangeDetectorRef, Compiler} from '#angular/core';
import { CHARTS } from './configuration.chart';
import { RcpChartDataService } from './data.service';
declare var d3, c3: any;
export class RcpChart {
id?: string;
name?: string;
type?: string;
parameters?: any[];
}
#Component({
selector: 'rcpchart',
providers: [RcpChartDataService],
template:`
<table style="border:solid">
<tr>
<td>
<div style="height: 300px">
<h1 *ngIf="chart">{{chart.name}}</h1>
<svg [id]="chart.id"></svg>
</div>
</td>
<td>
<div *ngIf="!data">
Data Not Available
</div>
</td>
</tr>
</table>
`
})
export class RcpChartComponent implements AfterViewInit{
#Input() chart: RcpChart;
data: any;
constructor(private rcpChartDataService: RcpChartDataService){}
ngAfterViewInit() {
console.log("CHART starts drawing AFTER VIEW INIT :" + this.chart.id);
this.drawChart(this.chart);
}
drawChartLine(chartConfig: RcpChart) {
//line chart
let chart = c3.generate({
bindto: '#' + chartConfig.id,
type: 'line',
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250],
['data2', 50, 20, 10, 40, 15, 25]
]
}
});
}
drawChart(chartConfig: RcpChart) {
if (chartConfig.type === 'line') this.drawChartLine(chartConfig);
}
getCharts(): void {
this.rcpChartDataService.getChartData().then(charts => this.chart = charts);
}
ngOnInit(): void {
this.getCharts();
}
I know it is a little long but I should have been missing something very easy, any help will be highly appreciated.

I think you are going the long route. Just follow the steps provided in the official google group of c3.js to configure it c3.js chart with the Angular2 project.

Related

How can I fix this error in Angular and output data to a PDF?

I'm trying to output data to a PDF with a button in a modal that is also displaying the same data. I have the data displaying in the modal with no issues, but I'm trying to create an option for the results to be downloaded to a PDF. I've been following a tutorial but currently receive an error in the console when loading my web application
core.js:6479 ERROR Error: Uncaught (in promise): NullInjectorError: R3InjectorError(AppModule)[MatDialogRef -> MatDialogRef -> MatDialogRef]:
NullInjectorError: No provider for MatDialogRef!
NullInjectorError: R3InjectorError(AppModule)[MatDialogRef -> MatDialogRef -> MatDialogRef]:
NullInjectorError: No provider for MatDialogRef!
I have a separate component just for holding the data and markup of the modal so that's where I'm also trying to implement the ability for a PDF option as well, in my auth-layout.component.ts
Here's my auth.component.html
<h2 mat-dialog-title>Order Summary</h2>
<div mat-dialog-content id="output" id="output">
<div>
<strong>Menu items:</strong>
<tr *ngFor="let item of invoice.serviceItems">
{{ item.serviceName }} ({{item.servicePrice | currency}})
</tr>
<br /> Subtotal: {{ invoice.getTotal() | currency }}
</div>
<hr />
<p>
Labor Cost: {{ invoice.getLaborTotal() | currency }}
</p>
<hr />
<p style="font-weight: bold;">Invoice total: {{ invoice.getInvoice() | currency }}</p>
</div>
<div mat-dialog-actions align="end">
<button mat-raised-button matDialogClose="cancel" color="primary">Cancel order</button>
<button mat-raised-button matDialogClose="confirm" color="accent" (click)="openPDF()">Confirm order</button>
</div>
and here's the auth-layout.component.ts
import { MatDialog, MatDialogRef, MAT_DIALOG_DATA, MatDialogModule} from '#angular/material/dialog';
import { Component, OnInit, Input, ElementRef, ViewChild, Inject } from '#angular/core';
import { Invoice } from '../invoice';
import jsPDF from 'jspdf';
import html2canvas from 'html2canvas';
#Component({
selector: 'app-auth-layout',
templateUrl: './auth-layout.component.html',
styleUrls: ['./auth-layout.component.css']
})
export class AuthLayoutComponent implements OnInit {
invoice: Invoice;
#ViewChild("output", {
static: true
}) output: ElementRef;
constructor(private dialogRef: MatDialogRef < AuthLayoutComponent > , #Inject(MAT_DIALOG_DATA) data: any) {
this.invoice = data.invoice;
console.log(this.invoice);
}
openPDF() {
const data = this.output.nativeElement;
const doc: jsPDF = new jsPDF("p", "mm", "a4");
doc.html(data, {
callback: (doc) => {
doc.output("dataurlnewwindow");
}
});
}
ngOnInit(): void {}
}
my services.component.ts as well, where i actually open the modal
import { Observable } from 'rxjs';
import { MatDialog, MatDialogRef, MAT_DIALOG_DATA} from '#angular/material/dialog';
import { ServiceHelper } from '../services.service';
import { ServiceItem } from '../services.interface';
import {MatCheckboxModule} from '#angular/material/checkbox';
import {FormBuilder, FormGroup, FormArray, FormControl } from '#angular/forms';
import {MatSnackBar} from '#angular/material/snack-bar';
import { FormsModule } from '#angular/forms';
import { Invoice } from '../invoice';
import { AuthLayoutComponent } from './../auth-layout/auth-layout.component';
import { jsPDF } from "jspdf";
import { Component, OnInit, Input, ElementRef, ViewChild } from '#angular/core';
#Component({
selector: 'app-services',
templateUrl: './services.component.html',
styleUrls: ['./services.component.css']
})
export class ServicesComponent {
#ViewChild("output", {
static: true
}) output: ElementRef;
serviceItems: ServiceItem[];
invoice: Invoice; //from invoice.ts
constructor(private dialog: MatDialog, private serviceHelper: ServiceHelper, private _snackBar: MatSnackBar) {
this.invoice = new Invoice();
this.serviceItems = serviceHelper.getServices();
}
clearInvoice(): void {
/**
* Iterate over the beverages array and set each objects checked property to false.
*/
for (let service of this.serviceItems) {
service.checked = false;
}
this.invoice = new Invoice(); // return a new instance of the Bill object.
}
openSnackBar(message: string) {
this._snackBar.open(message + " was added!");
}
//Opens modal with calculated results
submit() {
console.log(this.serviceItems)
for (let item of this.serviceItems) {
if (item.checked) {
this.invoice.addServiceItem(item);
}
}
console.log(this.invoice.serviceItems);
console.log(this.invoice.getTotal());
const dialogRef = this.dialog.open(AuthLayoutComponent, {
data: {
invoice: this.invoice
},
disableClose: true,
width: '800px'
})
dialogRef.afterClosed().subscribe(result => {
if (result === 'confirm') {
alert('Your order has been processed!');
this.clearInvoice();
} else {
alert('Your order has been canceled.');
this.clearInvoice();
}
})
}
}
did you add MatDialogModule to your app.module.ts?
it should look something like this
import {MatDialogModule} from '#angular/material/dialog';
#NgModule({
...
imports: [
...
MatDialogModule
...
]
})
export class AppModule {}
https://material.angular.io/components/dialog/api

Type 'Chart' is missing the following properties

I want to add the data from the endpoint response to my chart but when I try to initialize the chart , it throws an error of "Type Chart is missing the following properties from type any . How do I fix this error ? thanks in advance ? this is my component.ts code
import { Component, OnInit } from '#angular/core';
import {ApiService} from '../api.service';
import { Chart} from 'chart.js';
import { from } from 'rxjs';
//import { map } from 'rxjs/operators';
//import { Data} from '../../app/Data';
#Component({
selector: 'app-transactions',
templateUrl: './transactions.component.html',
styleUrls: ['./transactions.component.scss']
})
export class TransactionsComponent implements OnInit {
price = [];
time = [] ;
data = [] ;
chart = [] ;
constructor(private apiService : ApiService) { }
ngOnInit() {
this.apiService.dailychart()
.subscribe((response : any []) => {
console.log(response);
this.data = response;
Array.from(response).forEach( x =>{
this.time.push(x.description);
this.price.push(x.values) ;
})
this
this.chart = new Chart('canvas', {
type: 'line',
data: {
labels: this.time,
datasets: [
{
data: this.price,
borderColor: '#3cb371',
backgroundColor: "#0000FF",
}
]
},
options: {
legend: {
display: false
},
scales: {
xAxes: [{
display: true
}],
yAxes: [{
display: true
}],
}
}
});
});
}
}
This is my service class code , the response logs to the console but won't show on chart after removing the [] in front of the chart instance member in component.ts
import { Injectable } from '#angular/core';
import {HttpClient, HttpHeaders} from '#angular/common/http';
import {Observable} from 'rxjs';
#Injectable({
providedIn: 'root'
})
export class ApiService {
constructor(private httpclient : HttpClient ) { }
public dailychart() {
return this.httpclient.get<any>('https://api.coindesk.com/v1/bpi/currentprice.json')
}
}
Inside TransactionsComponent, you initialize chart with an array of any but in your code, you try to assign an instance of Chart. Declared chart as type Chart and it should work.
export class TransactionsComponent implements OnInit {
...
chart: Chart;

Error while loading components dynamically in angular 7. No component factory found

I need to load components dynamically to view on some button click.
I have created on directive and some components in my custom module.
But when I try to create new instance of component it says No component factory found.
Here is my code structure.
dashboard module
#NgModule({
declarations: [MainPageComponent, WidgetComponent, ChartsComponent, GraphsComponent, InfographicsComponent, InsertionDirective],
imports: [
CommonModule,
GridsterModule,
ButtonsModule,
ChartsModule,
DropDownsModule
],
entryComponents: [MainPageComponent, WidgetComponent, ChartsComponent, GraphsComponent, InfographicsComponent],
exports: [MainPageComponent, WidgetComponent, ChartsComponent, GraphsComponent, InfographicsComponent]
})
export class DashboardModule {
static customization(config: any): ModuleWithProviders {
return {
ngModule: DashboardModule,
providers: [
{ provide: Service, useClass: config.service }
]
}
}
}
dashboard/insert directive
import { Directive, ViewContainerRef } from '#angular/core';
#Directive({
selector: '[appInsertion]'
})
export class InsertionDirective {
constructor(public viewContainerRef: ViewContainerRef) { }
}
1. dashboard/mainMainPageComponent.ts
import { Component, OnInit, ViewChild, ComponentFactoryResolver, ComponentRef, Type } from '#angular/core';
import { Service } from 'src/app/services/service';
import { Widget } from 'src/app/interface/widget';
import { GridsterConfig, GridsterItem } from 'angular-gridster2';
import { SETTINGS } from '../settings'
import { InsertionDirective } from '../insertion.directive';
import { ChartComponent } from '#progress/kendo-angular-charts';
#Component({
selector: 'dasbhoard-main-page',
templateUrl: './main-page.component.html',
styleUrls: ['./main-page.component.css']
})
export class MainPageComponent implements OnInit {
componentRef: ComponentRef<any>;
childComponentType: Type<any>;
#ViewChild(InsertionDirective)
insertionPoint: InsertionDirective;
public title: string;
public widgets: Array<{ widget: Widget, grid: GridsterItem, type: string }> = [];
public options: GridsterConfig;
constructor(private service: Service, private componentFactoryResolver: ComponentFactoryResolver) {
this.title = 'Dashboard';
}
ngOnInit() {
this.options = {
itemChangeCallback: MainPageComponent.itemChange,
itemResizeCallback: MainPageComponent.itemResize,
};
}
addNewWidget(type: string) {
let widgetType = SETTINGS.widgetSetting[type];
let totalWidgets = this.widgets ? this.widgets.length : 0;
let componentFactory = this.componentFactoryResolver.resolveComponentFactory(widgetType.useClass);
//widgetType.useClass = ChartsComponent
// when I pass it statically its ok
//error here
let viewContainerRef = this.insertionPoint.viewContainerRef;
viewContainerRef.clear();
this.componentRef = viewContainerRef.createComponent(componentFactory);
this.widgets.push({ widget: { id: totalWidgets, header: `Widget ${totalWidgets} Header`, content: `<h1>Widget ${totalWidgets} Body</h4>` }, grid: { cols: 1, rows: 1, x: 0, y: 0 }, type: type });
}
}
dashboard/main-component/main-component.html
<ng-template appInsertion> </ng-template>
<button kendoButton(click) = "addNewWidget('charts')"[primary] = "true" class="pull-right" > Add Chart Widget </button>
I have each and every posts and all says you need to insert componets into entry points but I've already included all components to entry points. And all components are inside the same module but still it says no No component factory found for ChartsComponent. Did you add it to #NgModule.entryComponents?.
Any one please can you find out the where I'm doing wrong?
Thanks in advance.
I think it's just a typo:
In entryComponents you've written ChartsComponent and in the resolveComponentFactory method you've written ChartComponent
Could that be it?

Display Dynamic Data in Angular6 with GoogleChart

I use Angular Cli6, angularfire2 and firebase. I want to create a timeline with GoogleChart.
//GoogleChart.service
declare var google: any;
export class GoogleChartsBaseService
{
constructor() { google.charts.load('current', {'packages':["timeline"]}); }
protected buildChart(data: any[], chartFunc: any, options: any) : void {
var func = (chartFunc, options) =>
{
var datatable = google.visualization.arrayToDataTable(data);
chartFunc().draw(datatable, options);
};
var callback = () => func(chartFunc, options);
google.charts.setOnLoadCallback(callback);
}
}
TimelineChart.service
import { GoogleChartsBaseService } from './google-charts-base.service';
import { Injectable } from '#angular/core';
import { GanttChartConfig } from './../models/GanttChartConfig.model';
declare var google: any;
#Injectable()
export class GoogleGanttChartService extends GoogleChartsBaseService {
constructor() { super(); }
public BuildPieChart(elementId: string, data: any[], config: GanttChartConfig) : void {
var chartFunc = () => { return new google.visualization.Timeline(document.getElementById(elementId)); };
var options = {
traitement: config.traitement,
datedebut: config.datedebut,
datefin: config.datefin,
};
this.buildChart(data, chartFunc, options);
}
}
Timeline.html
<div id="{{elementId}}" ></div>
Timeline.ts
import { Component, Input, OnInit } from '#angular/core';
import { GoogleGanttChartService } from './../../services/google-gantt-chart.service';
import { GanttChartConfig } from './../../models/GanttChartConfig.model';
declare var google: any;
#Component({
selector: 'app-gantt',
templateUrl: './gantt.component.html',
styleUrls: ['./gantt.component.scss']
})
export class GanttComponent implements OnInit {
#Input() data: any[];
#Input() config: GanttChartConfig;
#Input() elementId: string;
constructor(private _ganttChartService: GoogleGanttChartService) {}
ngOnInit(): void {
this._ganttChartService.BuildPieChart(this.elementId, this.data, this.config);
}
}
And the component to display the graph :
Component.html
<div class="full"><app-gantt [data]="data1" [config]="config1" [elementId]="elementId1"></app-gantt></div>
Component.ts
import { Component, OnInit, Inject } from '#angular/core';
import { Patient } from '../models/patient.model';
import { Diagnostic } from '../models/diagnostic.model';
import { ActivatedRoute, Router } from '#angular/router';
import { PatientsService } from '../services/patients.service';
import { DiagnosticsService } from '../services/diagnostics.service';
import { PPSsService } from '../services/ppss.service';
import { AngularFireDatabase, AngularFireList, AngularFireObject, AngularFireAction } from 'angularfire2/database';
import { Location } from '#angular/common';
import { Observable } from 'rxjs/Observable';
import { GanttChartConfig } from './../models/GanttChartConfig.model';
import { PPS } from '../models/pps.model';
import {MAT_MOMENT_DATE_FORMATS, MomentDateAdapter} from '#angular/material-moment-adapter';
import {DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE} from '#angular/material/core';
import {MatDialog, MatDialogRef, MAT_DIALOG_DATA,MatDatepickerModule, MatFormFieldModule,} from '#angular/material';
import { FormControl, FormControlName, FormBuilder, FormGroup, Validators, ReactiveFormsModule, FormsModule } from '#angular/forms';
import { startWith } from 'rxjs/operators/startWith';
import { map, filter, catchError, mergeMap } from 'rxjs/operators';
#Component({
selector: 'app-pps',
templateUrl: './pps.component.html',
styleUrls: ['./pps.component.scss']
})
export class PpsComponent implements OnInit {
patientid: string;
patientToDisplay;
ppssToDisplay;
data1: any[];
config1: GanttChartConfig;
elementId1: string;
constructor(
private route: ActivatedRoute,
private location: Location,
private patientsService: PatientsService,
private diagnosticsService: DiagnosticsService,
private ppssService: PPSsService,
private router: Router,
public dialog: MatDialog,
){ }
ngOnInit() {
this.route.params.forEach((urlParameters) => {
this.patientid = urlParameters['id'];});
this.patientToDisplay =
this.patientsService.getSinglePatient(this.patientid);
this.ppssToDisplay = this.ppssService.getPPSByPatientid(this.patientid);
this.data1 = [[ 'traitement','start', 'end'],
[ 'Chirurgie', new Date(2017, 3, 29), new Date(2017, 3, 30)],
[ 'Chimiothérapie', new Date(2017, 2, 4), new Date(2018, 2, 4)],
[ 'Radiothérapie', new Date(2017, 2, 4), new Date(2018, 2, 4)]];
this.config1 = new GanttChartConfig( '',new Date (),new Date ());
this.elementId1 = 'myGanttChart';
Now i can display my graph easily with data write in my component
but my data are stocked in firebase like that :
I display the data with an observable from angularfire2
DATA.Service.TS
getPPSByPatientid(Patientid: string){
return this.database.list('/ppss', ref => ref.orderByChild("Patientid").equalTo(Patientid)).valueChanges();
}
I try this in my component .ts in order to have the good array for this.data1 but witout succes
Console.log(this.data1) send an array of undefined
let interestingFields = [ 'treatement','dateA', 'dateB'];
this.ppssToDisplay.subscribe(obj => {
this.data1 = [
interestingFields,
interestingFields.map(field => obj[field]),
];
console.log(this.data1);
});
Error:
core.js:1598 ERROR Error: Uncaught (in promise): Error: Not an array Error: Not an array
I wanted to put all of my code so you could have complete visualization of what I want to do.
My question is: Have I chosen the right solution or should I use a loop in my template to populate the chart?
And could someone show me the voice so I can sleep again (5 days lol)
It seems you have gotten the right solution. There is just one problem when getting your data to data1.
For the retrieved data to match the pattern on your data written in hard, you have to loop through it from the perspective of the retrieved data:
this.ppssToDisplay.subscribe(ppsList => {
this.data1 = [
interestingFields,
...ppsList.map(pps => interestingFields.map(field => pps[field]))
];
});
And there you go. That should solve your problem.

How implement Chart.js in Angular 2?

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 an external file(or link) and retrieve 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 used this approach because our service retrieves the data in asynchronous and, because of that, the data can be returned 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,{...})
}
}

Categories