Chart.js not working with Pug and Node for PDF - chart.js

I am trying to create a line chart inside a PDF file using Chart.js, Node, Pug and Headless chrome (html-pdf-chrome) and it is not working.
The rendered HTML works directly in browser, but the generated PDF is blank. Adding a timeout makes no difference with completionTrigger.
I am wondering if it is even possible to do this, and if so, where did I go wrong?
Node file:
const pug = require('pug');
const htmlPdf = require('html-pdf-chrome');
async function createPDF() {
const html = pug.renderFile('template.pug', {})
const options = {
port: 9222,
completionTrigger: new htmlPdf.CompletionTrigger.Timer(5000),
};
htmlPdf.create(html, options).then((pdf) => pdf.toFile('output.pdf'));
}
createPDF();
Pug template:
doctype html
html
head
meta(charset="utf-8")
title test
script(type="text/javascript", src='chart.js')//chart.js lib
script(type="text/javascript", src='scripts.js')
body
canvas#myChart(width='200' height='100' style='border:1px solid #000000;')
scripts file:
window.onload = function () {
const ctx = document.getElementById('myChart').getContext('2d');
const chart = new Chart(ctx, {
type: 'line',
data: {
labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
datasets: [{
label: 'My First dataset',
backgroundColor: 'rgb(255, 99, 132)',
borderColor: 'rgb(255, 99, 132)',
data: [0, 10, 5, 2, 20, 30, 45]
}]
},
options: {}
});
};

Related

How to compare one value to another in chartJS

I have been working on a broadband management website.I want to show the user how much data he/she has used.For example if the total data they have in their name is 300GB.If they have used 150GB the remaining is 150GB right?.How to do i visualize this using a doughnut chart,Using ChartJS.
I have some code going but im not sure how to accomplish this please help me out
var ctx = document.getElementById('myChart').getContext('2d');
var constdata=document.getElementById("constantdata").textContent;
var data=document.getElementById("data").textContent;
console.log(data);
var chart = new Chart(ctx, {
// The type of chart we want to create
type: 'doughnut',
// The data for our dataset
data: {
datasets: [{
label: 'My First dataset',
backgroundColor: ['red','green'],
borderColor: 'rgb(255, 99, 132)',
data: [300,150] //300 being the total data,150 being the data used
}]
},
// Configuration options go here
options: {}
But the above code isnt working out.Assume a doughnut chart,If the used data is 150GB(out of 300).The doughnut
chart must be like image1(please refer image 1)
But im getting image2(please refer image 2)
https://i.stack.imgur.com/nFTym.png //image 1
https://i.stack.imgur.com/MG99s.png //image 2
Assuming that the used data should appear in red, data should be defined as follows:
data: [used, total - used]
Please have a look at your amended code sample below.
const total = 300;
const used = 100;
var chart = new Chart(document.getElementById('myChart'), {
type: 'doughnut',
data: {
datasets: [{
label: 'My First dataset',
backgroundColor: ['red', 'green'],
borderColor: 'rgb(255, 99, 132)',
data: [used, total - used]
}]
},
options: {}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.min.js"></script>
<canvas id="myChart" height="90"></canvas>

How to extract ChartJs data and config properties

We're trying to give colleagues the ability to share ChartJS graphs with each other. Most of our current graphs are dynamic and users can apply filters (dates, add/remove data etc).
The plan is to have a button that, on click, will get the data and properties (labels, line colours, borderWidth, chart type etc) and pass this data via a url. The user can then send that link to someone else. They can open it up to view that chart captured as it was seen by the original user, like a screenshot, but with all the interactive features enabled.
E.g.
stackoverflow.com/shared_chart.php?conf=%7B%22responsive%22:true,%22responsiveA
When a chart is created by myChart = new Chart(ctx, config); ChartJs adds a lot of new properties to the chart object (e.g $plugin, _meta) that I don't need.
And, when I JSON.stringify(myChart.config) I get an error "Uncaught TypeError: Converting circular structure to JSON".
I've added the code needed to create a sample bar chart below:
// HTML needs a canvas element
<-- <canvas id="myChart"></canvas> -->
const ctx = $('#myChart');
let config;
let myChart;
// config would look something like this
config = {
type: 'bar',
data: {
labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
datasets: [{
label: 'Dataset 1',
backgroundColor: 'rgba(92,184,92,0.5)',
borderColor: 'rgba(92,184,92,1.000)',
borderWidth: 2,
data: [
1,2,3,4,3,2,1
]
}, {
label: 'Dataset 2',
backgroundColor: 'rgba(66,139,202,0.5)',
borderColor: 'rgba(66,139,202,1)',
borderWidth: 2,
data: [
7,2,3,1,5,2,1
]
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
legend: {
position: 'top',
},
title: {
display: true,
text: 'Chart.js Bar Chart'
}
}
}
myChart = new Chart(ctx,config);
On the page they are directed to, I'd like to grab the GET data and construct a new Chart.
You can exclude the extra properties that Chart.js adds. E.g.:
JSON.stringify(myChart.config, function(key, value) {
if (key === '_meta') return undefined;
else return value;
}

Dynamically populating data into chart in Chart.js

I have few charts ready in chart.js. I am trying to put the data that I have fetched through JSON file. How do I change the chart data automatically in a chart? I am getting json data from URL.
chartData1:{
labels: ["01 Jan","02 Jan","03 Jan","04 Jan","05 Jan","06
Jan","07 Jan"],
datasets: [{
label: "s1",
data:
[100,0,1,0,0,1,0,0,0,1,2,3,0,0,0,0,1,1,1,0,0,0,2,1,1,0,1,3,2,1,0],
fill:false,
borderColor: 'Orange',
lineTension:0,
borderWidth:2,
radius:2
},
{
label: "s2",
data:
[2,3,4,1,4,5,3,2,0,1,0,3,5,6,3,7,2,0,5,3,1,2,3,1,0,5,4,5,8,6,2],
fill:false,
borderColor: 'Violet',
lineTension:0,
borderWidth:2,
radius:2
}
]
},
"line-chart" is the id of the <canvas> where you want to display chart.
Try with this.
var chart1 = document.getElementById("line-chart").getContext("2d");
window.myLine = new Chart(chart1).Line(chartData1, {
responsive: true,
scaleLineColor: "rgba(0,0,0,.2)",
scaleGridLineColor: "rgba(0,0,0,.05)",
scaleFontColor: "#c5c7cc"
});

Chart.js - How to set a line chart dataset as disabled on load

Using chart.js v2, is it possible to mark a dataset in a line chart as being disabled on initial load?
Didn't find an option for it in the documentation.
Yes, there is a "hidden" flag in ChartJS.
eg.
data:
{
datasets: [
{
data: [1,2,3],
label: 'My First Dataset',
hidden: true,
},
],
}
See this issue on GitHub: https://github.com/chartjs/Chart.js/issues/689
The accepted solution has the downside, that hiding/unhiding signals might sometimes fail after initializing the chart like that.
It might be a better idea to change it in the current metadata of the dataSet, which holds the actual data that is used by the chart:
chart.data.datasets.forEach((dataSet, i) => {
var meta = chart.getDatasetMeta(i);
meta.hidden = (<your-condition-here>);
});
this.chart.update();
If you are using angular-chartjs, then you can add the properties of the dataset in the chart-dataset-override property:
For example:
HTML:
<div class="container" ng-app="app" ng-controller="ChartCtrl">
<canvas id="bar" class="chart chart-bar" chart-data="data" chart-labels="labels" chart-series="series" chart-dataset-override="datasetOverride">
</canvas>
</div>
Javascript:
Chart.defaults.global.legend.display = true;
angular.module("app", ["chart.js"])
.controller("ChartCtrl", function($scope) {
$scope.labels = ['2006', '2007', '2008', '2009', '2010', '2011', '2012'];
$scope.series = ['Series A', 'Series B'];
$scope.data = [
[65, 59, 80, 81, 56, 55, 40],
[28, 48, 40, 19, 86, 27, 90]
];
$scope.datasetOverride = [{}, {
hidden: true,
}];
});

Load ChartJS via VueJS - ChartJS empty and 0px dimension

Alright, so I am trying to create a ChartJS instance via VueJS so that I could easily update its data via AJAX requests inside the component.
Basically it is working, the ChartJS instance gets created but it is empty and has a height and width of 0 and when I resize it via console it is still empty.
So what would be the best way of creating a "ChartJS Component" with VueJS or where is the fault in my code below?
The very basic way I want to load chart is like this.
<chart :resource="'https://httpbin.org/get'"></chart>
This is the basic component
var Vue = require('vue');
Vue.component('chart', {
template: require('./template.html'),
props: ['resource'],
data: function() {
return {
startingData: {},
latestLabel: {},
}
},
ready: function() {
// here I would load the js data and set the startingData
},
});
This is the directive which I use to pass down the data from the component. I do it this way to get this.el so that I can get the Context of it
Vue.directive('loadData', function(value) {
var startingData = {
labels: [1, 2, 3, 4, 5, 6, 7],
datasets: [{
fillColor: "rgba(151,187,205,0.2)",
strokeColor: "rgba(151,187,205,1)",
pointColor: "rgba(151,187,205,1)",
pointStrokeColor: "#fff",
data: [28, 48, 40, 19, 86, 27, 90]
}]
},
latestLabel = startingData.labels[6];
var liveChart = new Chart(this.el.getContext('2d')).Bar(startingData);
setInterval(function() {
liveChart.addData([Math.random() * 100], ++latestLabel);
liveChart.removeData();
}, 1000);
});
This is the template of the component
<canvas width="960" height="300" v-load-data="startingData"></canvas>
You are concerned by this issue. Your graph does not render because, as you pointed out, the graph has a height and width of 0.
I had this problem while working with tabsets, and I solved it by redrawing the graph with a directive like this :
app.directive('graphCanvasRefresh', ['$compile', function($compile) {
function link(scope, elem, attrs) {
function refreshDOM() {
var markup = '<canvas class="chart chart-pie" id="graph" data="entityGraph.data" labels="entityGraph.labels" legend="true" colours="graphColours" ></canvas>';
var el = angular.element(markup);
compiled = $compile(el);
elem.html('');
elem.append(el);
compiled(scope);
};
// Refresh the DOM when the attribute value is changed
scope.$watch(attrs.graphCanvasRefresh, function(value) {
refreshDOM();
});
// Clean the DOM on destroy
scope.$on('$destroy', function() {
elem.html('');
});
};
return {
link: link
};
}]);
Hope this can help you