Chart is not working in Angular2 [duplicate] - charts

This question already has answers here:
Chart.js not showing in Angular2 if it doesn't exist on the main page
(2 answers)
Closed 6 years ago.
I am trying to create Bar Chart using this github repo. But my chrome does not display chart.
Here is my plnkr. I don't know what i am doing wrong.
Here is my updated code:
app.ts
import {Component, Pipe, PipeTransform} from 'angular2/core';
import {CORE_DIRECTIVES, NgClass, FORM_DIRECTIVES, Control, ControlGroup, FormBuilder, Validators} from 'angular2/common';
import {CHART_DIRECTIVES} from './ng2-charts.ts';
#Component({
selector: 'my-app',
templateUrl: 'mytemplate.html',
directives: [CHART_DIRECTIVES, NgClass, CORE_DIRECTIVES, FORM_DIRECTIVES]
})
export class AppComponent {
constructor() {
console.log('bar demo');
}
private barChartOptions = {
scaleShowVerticalLines: false,
responsive: true,
multiTooltipTemplate: '<%if (datasetLabel){%><%=datasetLabel %>: <%}%><%= value %>'
};
private barChartLabels = ['2006', '2007', '2008', '2009', '2010', '2011', '2012'];
private barChartSeries = ['Series A', 'Series B'];
public barChartType = 'Bar';
private barChartLegend:boolean = true;
private barChartData = [
[65, 59, 80, 81, 56, 55, 40],
[28, 48, 40, 19, 86, 27, 90]
];
// events
chartClicked(e:any) {
console.log(e);
}
chartHovered(e:any) {
console.log(e);
}
}
app.html
<base-chart class="chart"
[data]="barChartData"
[labels]="barChartLabels"
[options]="barChartOptions"
[series]="barChartSeries"
[legend]="barChartLegend"
[chartType]="barChartType"
(chartHover)="chartHovered($event)"
(chartClick)="chartClicked($event)"></base-chart>
Suggest me if there is any another library for displaying data on the bar chart for angular2.

Eleboration of #Thierry's answer with example.
updated code is here:
app.ts
import {Component, DynamicComponentLoader, Injector} from 'angular2/core';
import {CORE_DIRECTIVES, NgClass, FORM_DIRECTIVES, Control, ControlGroup, FormBuilder, Validators} from 'angular2/common';
import {ChartDirective} from './charts.ts';
#Component({
selector: 'my-app',
templateUrl: 'mytemplate.html',
directives: [ChartDirective, NgClass, CORE_DIRECTIVES, FORM_DIRECTIVES]
})
export class AppComponent {
constructor() {
}
}
app.html
<div class="container details-container">
<topics></topics>
</div>
<div class="graph-container">
<div class="row no-pad" style="position: relative;">
<div style="margin-left:14px; z-index: 100; height: 250px;">
<canvas id="myChart" chart height="250" width="350"></canvas>
</div>
</div>
</div>
chart.ts
import {Directive, ElementRef, Renderer, Input} from 'angular2/core';
#Directive({
selector: '[chart]'
})
export class ChartDirective {
constructor(el: ElementRef, renderer: Renderer) {
//el.nativeElement.style.backgroundColor = 'yellow';
var data = {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [
{
label: "My First dataset",
fillColor: "rgba(220,220,220,0.5)",
strokeColor: "rgba(220,220,220,0.8)",
highlightFill: "rgba(220,220,220,0.75)",
highlightStroke: "rgba(220,220,220,1)",
data: [65, 59, 80, 81, 56, 55, 40]
},
{
label: "My Second dataset",
fillColor: "rgba(151,187,205,0.5)",
strokeColor: "rgba(151,187,205,0.8)",
highlightFill: "rgba(151,187,205,0.75)",
highlightStroke: "rgba(151,187,205,1)",
data: [28, 48, 40, 19, 86, 27, 90]
}
]
};
var options = {
scaleBeginAtZero : true,scaleShowGridLines : true,
scaleGridLineColor : "rgba(0,0,0,.05)",
scaleGridLineWidth : 1,
scaleShowHorizontalLines: true,
scaleShowVerticalLines: true,
barShowStroke : true,
barStrokeWidth : 2,
barValueSpacing : 5,
barDatasetSpacing : 1,
legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"background-color:<%=datasets[i].fillColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>"
}
var ctx: any = el.nativeElement.getContext("2d");
var BarChart = new Chart(ctx);
BarChart.Bar(data, options);
}
}
working plnkr http://plnkr.co/edit/Vfsert1sAJ4dsVR4MdyV?p=preview

I think that this question could help you:
Chart.js not showing in Angular2 if it doesn't exist on the main page

Related

Time Serie issue

I am working with Nextjs 13, chart.js v4.0.1 and react-chartjs-2 v5.0.1.
I could succesfully plot graph with a classic scale, but now that I am trying with x axis in serie, I have a weird error "Error: Canvas is already in use. Chart with ID '0' must be destroyed before the canvas with ID '' can be reused."
Do you have any idea why this occur ? This is my sample code :
"use client";
import React from "react";
import { Chart as ChartJS, TimeScale, LinearScale, PointElement, LineElement, Title, Tooltip, Legend } from "chart.js";
import { Line } from "react-chartjs-2";
ChartJS.register(TimeScale, LinearScale, PointElement, LineElement, Title, Tooltip, Legend);
export const options = {
plugins: {
legend: {
position: "bottom" as const,
},
title: {
display: false,
// text: "Chart.js Line Chart",
},
},
response: true,
scales: {
x: {
type: "time",
time: {
unit: "day",
},
},
},
maintainAspectRatio: false,
};
export const data = {
datasets: [
{
label: "Estimation",
data: [
{
x: new Date("2020-01-01"),
y: 50,
},
{
x: new Date("2020-01-02"),
y: 60,
},
],
borderColor: "rgb(255, 99, 132)",
backgroundColor: "rgba(255, 99, 132, 0.5)",
tension: 0.25,
},
],
};
export default function Kikoo() {
return (
<div className="relative px-4 py-8" style={{ margin: "auto", width: "100%", height: "100%" }}>
<Line options={options} data={data} />
</div>
);
}
Thank you so much in advance, I am seriously stuck on that one :/

How to add Chart background borderColor gradient to Next.js

I want to add gradient to my chart background. Here below an example:
I'm using Next.js and react-chart.js.
Here below an example of my code:
import { ChartProps } from "./Chart.props";
import styles from "./Chart.module.css";
import React, { useState, useEffect, useRef } from 'react';
import { Chart as ChartJS, ArcElement, CategoryScale, LinearScale, PointElement, LineElement, Title, Tooltip, Legend, ScriptableContext, } from "chart.js";
import { Chart, Line } from "react-chartjs-2";
ChartJS.register(ArcElement, Tooltip, Legend, CategoryScale, LinearScale, PointElement, LineElement);
import { optionsChart } from "./ChartConfig.js";
export const CoinPriceChart = (props) => {
const data = {
labels: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14"],
datasets: [
{
data: [22, 45, 23, 41, 18, 11, 32, 31, 63, 54, 45, 49, 54, 36],
pointRadius: 0,
pointHoverRadius: 2,
borderColor: "rgba(91,56,237,255)",
}
],
options: {
...optionsChart
},
};
return (
<div
className={styles.CardList}
{...props}
>
<Line id="myChart" data={data} options={optionsChart}/>
</div>
);
};
Once I'd tried something like this:
But in React (not in Node.js). In Node.js it doesn't work for me.
And here below how my chart looks like (now):
Waiting for your propositions. Thanks in advance!
This is because in chart.js V3 the line chart does not fill by default. You will need to import the filler plugin and tell the dataset to fill like so:
import {Chart, Filler} from 'chart.js'
import {Chart as ReactChart, Line} from 'react-chartjs-2'
Chart.register(Filler);
const data = {
labels: labels,
datasets: [{
data: data,
fill: true // Set fill to true to enable the backgroundColor under the line
}]
}
//Importing stuff
import React from 'react';
import { Chart as ChartJS, ArcElement, CategoryScale, LinearScale, PointElement, LineElement, Filler, Tooltip, Legend, ScriptableContext, } from "chart.js";
import { Chart as ReactChart, Line } from "react-chartjs-2";
ChartJS.register(ArcElement, Tooltip, Filler, Legend, CategoryScale, LinearScale, PointElement, LineElement);
// init our Line Chart with gradient of course
export const CoinPriceChart = (props) => {
const data = {
labels: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14"],
datasets: [
{
data: [22, 45, 23, 41, 18, 11, 32, 31, 63, 54, 45, 49, 54, 36],
pointRadius: 0,
pointHoverRadius: 2,
backgroundColor: (context: ScriptableContext<"line">) => {
const ctx = context.chart.ctx;
const gradient = ctx.createLinearGradient(0, 0, 0, 250);
gradient.addColorStop(0, "rgba(91,56,237,0.45)");
gradient.addColorStop(1, "rgba(91,56,237,0.0)");
return gradient;
}, //background gradient color
borderColor: "rgba(91,56,237,255)", //line color
fill: true, // this line allow us to use background gradient
}
],
};
return (
<div
{...props}
>
<Line id="myChart" data={data} />
</div>
);
};
And here below result how it looks like:
And do not forget about importing this component to your main app.js file
import { CoinPriceChart } from '../shared/components';//your path of course
<CoinPriceChart data={coinData}></CoinPriceChart>

Chart.js in Ionic 5

i have been trying to use the Chart.js in Ionic 5 by looking this tutorial (https://ichi.pro/es/ionic-5-charts-graphs-usando-la-biblioteca-chartjs-102145521332905)
But I get this error:
The code is almost identical except for the file names.
Don't really understand why it happens, any help is welcome.
import { Component, AfterViewInit, ViewChild , ElementRef } from '#angular/core';
import {Chart} from "chart.js";
#Component({
selector: 'app-tab3',
templateUrl: 'tab3.page.html',
styleUrls: ['tab3.page.scss']
})
export class Tab3Page implements AfterViewInit{
#ViewChild('lineCanvas') private lineCanvas: ElementRef;
lineChart: any;
constructor() { }
ngAfterViewInit() {
this.lineChartMethod();
}
lineChartMethod() {
this.lineChart = new Chart(this.lineCanvas.nativeElement, {
type: 'line',
data: {
labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'November', 'December'],
datasets: [
{
label: 'Sell per week',
fill: false,
//lineTension: 0.1,
backgroundColor: 'rgba(75,192,192,0.4)',
borderColor: 'rgba(75,192,192,1)',
borderCapStyle: 'butt',
borderDash: [],
borderDashOffset: 0.0,
borderJoinStyle: 'miter',
pointBorderColor: 'rgba(75,192,192,1)',
pointBackgroundColor: '#fff',
pointBorderWidth: 1,
pointHoverRadius: 5,
pointHoverBackgroundColor: 'rgba(75,192,192,1)',
pointHoverBorderColor: 'rgba(220,220,220,1)',
pointHoverBorderWidth: 2,
pointRadius: 1,
pointHitRadius: 10,
data: [65, 59, 80, 81, 56, 55, 40, 10, 5, 50, 10, 15],
spanGaps: false,
}
]
}
});
}
}
Here's the HTML
<ion-content [fullscreen]="true">
<div class="ion-padding">
<ion-card>
<ion-card-header>
Line Chart
</ion-card-header>
<ion-card-content>
<canvas #lineCanvas style="position: relative; height:20vh; width:40vw"></canvas>
</ion-card-content>
</ion-card>
</div>
</ion-content>
Chart.js need to register the controller before loading datas,but whatever the underneath mechanics, here is from the chart.js docs the proper way to init Chart in typescript :
A short registration format is also available to quickly register
everything.
import { Chart, registerables } from 'chart.js';
Chart.register(...registerables);
And finally there is an separate
path to do just the above for you, in one line:
import Chart from 'chart.js/auto';
source :https://www.chartjs.org/docs/master/getting-started/integration.html
import { Chart, registerables } from 'chart.js';
Chart.register(...registerables);
Just put this...

Print PDF in ionic 3

I am using PDFMake for creating the pdf with my predefined Document definition. In my old ionic 1 project, I am passing the encoded string to print function which works fine. here is the code for old ionic 1
var dd = $scope.createDocumentDefinition();
$timeout(function () {
var pdf = pdfMake.createPdf(dd);
pdf.getBase64(function (encodedString) {
console.log(encodedString);
$ionicLoading.hide();
window.plugins.PrintPDF.print({
data: encodedString,
type: 'Data',
title: 'Print Document',
success: function () {
console.log('success');
},
error: function (data) {
data = JSON.parse(data);
console.log('failed: ' + data.error);
}
});
});
}, 1000);
Now I am upgrading my project to Ionic 3 so I tried the same thing but the output is different here is my new ionic 3 code. printer open but instead of printing as per my document definition it just prints the encoded string.
let printer_ = this.printer;
var dd = this.createDocumentDefinition();
var pdf = pdfMake.createPdf(dd);
pdf.getBase64(function (_encodedString) {
let options: PrintOptions = {
name: 'MyDocument'
};
console.log(JSON.stringify(pdf));
printer_.print(_encodedString, options).then((msg)=>{
console.log("Success",msg);
},(error) => {
console.log("Error", error);
});
});
Any idea how to use this in ionic 3 ??
You can use pdfmake for generate PDF using ionic.
First you need to install plugin for file and file opener.
ionic cordova plugin add cordova-plugin-file-opener2
ionic cordova plugin add cordova-plugin-file
After that install NPM package of file, FileOpener and PDF make
npm install pdfmake
npm install #ionic-native/file-opener
npm install #ionic-native/file
Open your src/app.module.ts and include file and fileoperner reference:
import { File } from '#ionic-native/file';
import { FileOpener } from '#ionic-native/file-opener';
Add File and FileOpener in provider
providers: [
StatusBar,
SplashScreen,
{provide: ErrorHandler, useClass: IonicErrorHandler},
File,
FileOpener
]
I am generating a template UI looks like this:
<ion-header>
<ion-navbar>
<ion-title>
Ionic PDF
</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<ion-item>
<ion-label stacked>From</ion-label>
<ion-input [(ngModel)]="letterObj.from"></ion-input>
</ion-item>
<ion-item>
<ion-label stacked>To</ion-label>
<ion-input [(ngModel)]="letterObj.to"></ion-input>
</ion-item>
<ion-item>
<ion-label stacked>Text</ion-label>
<ion-textarea [(ngModel)]="letterObj.text" rows="10"></ion-textarea>
</ion-item>
<button ion-button full (click)="createPdf()">Create PDF</button>
<button ion-button full (click)="downloadPdf()" color="secondary" [disabled]="!pdfObj">Download PDF</button>
</ion-content>
After that your home.component.ts code looks like this:
import { Component } from '#angular/core';
import { NavController, Platform } from 'ionic-angular';
import pdfMake from 'pdfmake/build/pdfmake';
import pdfFonts from 'pdfmake/build/vfs_fonts';
pdfMake.vfs = pdfFonts.pdfMake.vfs;
import { File } from '#ionic-native/file';
import { FileOpener } from '#ionic-native/file-opener';
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
letterObj = {
to: '',
from: '',
text: ''
}
pdfObj = null;
constructor(public navCtrl: NavController, private plt: Platform, private file: File, private fileOpener: FileOpener) { }
createPdf() {
var docDefinition = {
content: [
{ text: 'REMINDER', style: 'header' },
{ text: new Date().toTimeString(), alignment: 'right' },
{ text: 'From', style: 'subheader' },
{ text: this.letterObj.from },
{ text: 'To', style: 'subheader' },
this.letterObj.to,
{ text: this.letterObj.text, style: 'story', margin: [0, 20, 0, 20] },
{
ul: [
'Bacon',
'Rips',
'BBQ',
]
}
],
styles: {
header: {
fontSize: 18,
bold: true,
},
subheader: {
fontSize: 14,
bold: true,
margin: [0, 15, 0, 0]
},
story: {
italic: true,
alignment: 'center',
width: '50%',
}
}
}
this.pdfObj = pdfMake.createPdf(docDefinition);
}
downloadPdf() {
if (this.plt.is('cordova')) {
this.pdfObj.getBuffer((buffer) => {
var blob = new Blob([buffer], { type: 'application/pdf' });
// Save the PDF to the data Directory of our App
this.file.writeFile(this.file.dataDirectory, 'myletter.pdf', blob, { replace: true }).then(fileEntry => {
// Open the PDf with the correct OS tools
this.fileOpener.open(this.file.dataDirectory + 'myletter.pdf', 'application/pdf');
})
});
} else {
// On a browser simply use download!
this.pdfObj.download();
}
}
}

Chartjs.org Chart only displaying in one page

My charts works well on the same page but when I put on different pages, only the first one works fine.
ex:
Page1.html
<div class="wrapper">
<canvas id="pieChart" width="200px" height="200px"></canvas>
</div>
Page2.html
<div class="wrapper">
<canvas id="lineChart" width="200px" height="200px"></canvas>
</div>
JS
//page1.html
//piechart
var pieVar = {
type: 'pie',
data: {
labels: ["Yes", "No"],
datasets: [
{
data: [60, 40],
backgroundColor: [
"#FF6384",
"#36A2EB"
],
hoverBackgroundColor: [
"#FF6384",
"#36A2EB"
]
}
]
},
options: {
scales: {
xAxes: [{
display: true
}]
}
}
}
//page2.html
//line chart
var lineVar = {
type: 'line',
data: {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [
{
label: "My First dataset",
fill: true,
lineTension: 0.2,
backgroundColor: "rgba(75,192,192,0.4)",
borderColor: "rgba(75,192,192,1)",
borderCapStyle: 'butt',
borderDash: [],
borderDashOffset: 0.0,
borderJoinStyle: 'miter',
pointBorderColor: "rgba(75,192,192,1)",
pointBackgroundColor: "#fff",
pointBorderWidth: 1,
pointHoverRadius: 10,
pointHoverBackgroundColor: "rgba(255,0,0,1)",
pointHoverBorderColor: "rgba(255,0,0,1)",
pointHoverBorderWidth: 2,
pointRadius: 1,
pointHitRadius: 10,
data: [65, 59, 80, 81, 56, 55, 40],
spanGaps: false,
}
]
},
options: {
scales: {
xAxes: [{
display: true
}]
}
}
}
window.onload = function(){
//piechart
var pieCtx = document.getElementById("pieChart");
var myPieChart = new Chart(pieCtx, pieVar);
//linechart
var lineCtx = document.getElementById("lineChart");
var myLineChart = new Chart(lineCtx, lineVar);
};
In this codepen works fine because it's the same page..
CODEPEN
It sounds like you're loading the same JavaScript file (which contains the configurations for both of your charts) in both of your pages. The problem is since you're using a single JavaScript file with two chart definitions, the chart you try to create that doesn't exist in the html is throwing an error because you are passing in an empty context.
window.onload = function(){
//piechart (this will be null on page2.html)
var pieCtx = document.getElementById("pieChart");
// You are passing in a null pieCtx on page2.html because there is no element with an id = "pieChart"
var myPieChart = new Chart(pieCtx, pieVar);
//linechart (this will be null on page1.html)
var lineCtx = document.getElementById("lineChart");
// You are passing in a null lineCtx on page1.html because there is no element with an id = "lineChart"
var myLineChart = new Chart(lineCtx, lineVar);
};
You should either split your JavaScript file into two files so that the first page only includes the definition for the first chart and the second page only includes the definition for the second chart. Or, add some conditions to prevent trying to create the empty chart (like this).
window.onload = function(){
//piechart (this will be null on page2.html)
var pieCtx = document.getElementById("pieChart");
if (pieChart) {
var myPieChart = new Chart(pieCtx, pieVar);
}
//linechart (this will be null on page1.html)
var lineCtx = document.getElementById("lineChart");
if (lineChart) {
var myLineChart = new Chart(lineCtx, lineVar);
}
};