Reputation: 11
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.
Upvotes: 1
Views: 1474
Reputation: 955
My code bellow builds a snippet compatible to stackoverflow.
It works basically, but it still needs some finish work, especially when using plugins.
The following javascript code retrieves most of the configuration of the Chart instance and copies to clipboard a webpage with a compatible chart. You may paste the clipboard in a snippet in a stackoverflow.com question or answer.
let {options, plugins, data} = chart_instance.config;
//optionally filter out hidden datasets
data.datasets = data.datasets.filter(
(ds, i) => info.chart.isDatasetVisible(i));
let snippet = `
<script>
const data = ${JSON.stringify(data, null, '\t')};
const plugins = ${JSON.stringify(plugins, null, '\t')};
const options = ${JSON.stringify(options, null, '\t')};
</script>
<script src="https://cdn.jsdelivr.net/npm/chart.js@^4"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@^2"></script>
<script src="https://cdn.jsdelivr.net/npm/luxon@^2"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-luxon@^1"></script>
<div class="chart" style="height:184px">
<canvas id="myChart"></canvas>
</div>
<script>
const ctx = document.getElementById('myChart');
chart = new Chart(ctx, {
type: 'line',
//not working yet
//plugins: [ChartDataLabels],
data,
options,
}
);
</script>
`;
navigator.clipboard.writeText(snippet)
.then(() => {
alert('clipboard successfully set');
})
.catch(error => {
alert('clipboard write failed', error);
});
Good luck!
Upvotes: 0
Reputation: 19004
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;
}
Upvotes: 1