How to reference array results into Chartjs dataset in Javascript - javascript

I have managed to get a count of items in list by status, but cant seem to figure out how to add the data into Chart.js. I have tried referencing my dataset from within the chart but that does not seem to work. Any assistance would be greatly appreciated. I have pieced together some code to try to get this to work but cant seem to get this last piece. ps. This code is being used in content editor in SharePoint.
Thank you,
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<button onclick="GetListItems();" type="button">Get All List Items​</button>
<div>
<canvas id="myChart"></canvas>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
function GetListItems() {
var url = "https://contoso.sharepoint.com/sites/Mysite/_api/web/lists/getByTitle('Mylist')/items?$top=500";
$.ajax({
url: url,
type: "GET",
headers: {
"accept": "application/json; odata=verbose"
},
success: onSuccess
});
}
function onSuccess(data) {
var items = data.d.results;
const MyDataset = [];
var NewItems = items.filter(function(ItemStatus) {
return ItemStatus.Status == "New";
});
var InProcItems = items.filter(function(ItemStatus) {
return ItemStatus.Status == "In Process";
});
var CompItems = items.filter(function(ItemStatus) {
return ItemStatus.Status == "Completed";
});
MyDataset.push(NewItems.length);
MyDataset.push(InProcItems.length);
MyDataset.push(CompItems.length);
console.log(MyDataset);
}
const labels = ['New', 'Completed', 'Inproccess'];
const data = {
labels: labels,
datasets: [{
label: 'My First dataset',
backgroundColor: 'rgb(255, 99, 132)',
borderColor: 'rgb(255, 99, 132)',
data: [5, 5, 5, 2, 2, 30, 45],// use MyDataset here instead of random.
}]
};
const config = {
type: 'bar',
data: data,
options: {}
};
</script>
<script>
const myChart = new Chart(
document.getElementById('myChart'),
config
);
</script>

That should do what's you expect. I cannot test because data ajax call is not public.
<!-- External Lib -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<!-- HTML / Template -->
<button onclick="GetListItems();" type="button">Get All List Items​</button>
<div>
<canvas id="myChart"></canvas>
</div>
<!-- Javascript -->
<script>
function GetListItems() {
var url = "https://contoso.sharepoint.com/sites/Mysite/_api/web/lists/getByTitle('Mylist')/items?$top=500";
$.ajax({
url: url,
type: "GET",
headers: {
"accept": "application/json; odata=verbose"
},
success: onSuccess
});
}
function onSuccess(data) {
var items = data.d.results;
var MyDataset = [];
var NewItems = items.filter(function(ItemStatus) {
return ItemStatus.Status == "New";
});
var InProcItems = items.filter(function(ItemStatus) {
return ItemStatus.Status == "In Process";
});
var CompItems = items.filter(function(ItemStatus) {
return ItemStatus.Status == "Completed";
});
MyDataset.push(NewItems.length);
MyDataset.push(InProcItems.length);
MyDataset.push(CompItems.length);
console.log(MyDataset);
createChar(MyDataset);
}
function createChar(dataset) {
const labels = ['New', 'Inproccess', 'Completed'];
const data = {
labels: labels,
datasets: [{
label: 'My First dataset',
backgroundColor: 'rgb(255, 99, 132)',
borderColor: 'rgb(255, 99, 132)',
data:dataset
}]
};
const config = {
type: 'bar',
data: data,
options: {}
};
const myChart = new Chart(
document.getElementById('myChart'),
config
);
}
</script>

You specify 3 labels and provide 7 element in data.
To resolve your problem, try with a simple config
const config = {
type: 'bar',
labels: labels // Your array of label
data: {
datasets: [{
data: [1, 2, 3], // Random data
}],
}
};
When that display something, try to add complexity.
By guessing, I believe you want something like that
const config = {
type: 'bar',
labels: labels, // Your array of label
data: {
datasets: [{
data: [
{x:'New', y:1},{x:'Completed', y:10},{x:'Inproccess', y:100},
{x:'New', y:2},{x:'Completed', y:20},{x:'Inproccess', y:200},
{x:'New', y:3},{x:'Completed', y:30},{x:'Inproccess', y:300},
]
}]
}
};
It's hard to help you as you didn't specify what kind of result chart you want to see...
your code working (snippet)
const labels = ['New', 'Completed', 'Inproccess'];
const config = {
type: 'bar',
labels: labels,
data: {
datasets: [{
label : 'Chart1',
data: [
{x:'New', y:1},{x:'Completed', y:10},{x:'Inproccess', y:100},
{x:'New', y:2},{x:'Completed', y:20},{x:'Inproccess', y:200},
{x:'New', y:3},{x:'Completed', y:30},{x:'Inproccess', y:300},
]
}]
}
};
const myChart = new Chart(
document.getElementById('myChart'),
config
);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<div>
<canvas id="myChart"></canvas>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>

Related

Unable to render two datasets from the controller in View

I am trying to draw a two-line chart with two datasets that share the same labels using chart.js on my ASP.NET MVC app.
I am only getting the data from "Value" plotted on the chart and not "Age" and I cannot find the reason why.
Relevant Controller code:
public ActionResult GetLineChartData()
{
List <LineChartData> dataForLineChart = new List <LineChartData> ();
dataForLineChart.Add(new LineChartData {
Date = DateTime.NOW, Value = 100, Age = 20
});
return Json(dataForLineChart, JsonRequestBehavior.AllowGet);
}
Relevant View code:
$.ajax({
type: "Post",
url: '#Url.Action("GetLineChartData", "Posts")',
contentType: false,
processData: false,
data: dataFromForm,
dataType: "json",
traditional: true,
success: function (data) {
console.log(data);
var labels = data.map(function (e) {
return e.Date;
});
var data = data.map(function (e) {
return e.Value;
});
var data2 = data.map(function (e) {
return e.Age;
});
var ctx = scatterChart.getContext('2d');
var config = {
type: 'line',
data: {
labels: labels,
datasets: [{
label: "Test"
data: data,
backgroundColor: 'rgba(0, 119, 204, 0.3)'
},
{
label: "Test",
data: data2,
backgroundColor: 'rgba(242, 204, 143, 1)'
}
]
}
};
}
});
(Some code I do not consider important is hidden)
Issue & Concern
Because the below line overwrites the original data value.
var data = data.map(function (e) {
return e.Value;
});
After the above line, now the data array was overwritten as an array of integers instead of an array of objects. Based on your sample response from API, the current value of data will be: [100].
var data2 = data.map(function (e) {
return e.Age;
});
From the above line, it can't find the Age property in the element. Hence the result of data2 will be: [undefined].
This is why the data2 is not rendered in the chart.
Solution
Create another variable for the data transformation to avoid overwriting the existing data value.
var dataset = data.map(function (e) {
return e.Value;
});
var dataset2 = data.map(function (e) {
return e.Age;
});
var config = {
type: 'line',
data: {
labels: labels,
datasets: [
{
label: 'Test',
data: dataset,
backgroundColor: 'rgba(0, 119, 204, 0.3)',
},
{
label: 'Test',
data: dataset2,
backgroundColor: 'rgba(242, 204, 143, 1)',
},
],
},
};
Demo # StackBlitz

How can I use embedded twitter tweets as a tooltip for each plot on a scatter chart?

// both being used
// <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
[// <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>][1]
const externalTooltipHandler = (context) => {
//does not log anything?
console.log(context);
return context;
};
const chartData = {
datasets: [{
label: ['Tweets'],
data: [],
backgroundColor: 'rgb(255, 255, 255)'
}],
};
const config = {
type: 'scatter',
data: chartData,
options: {
scales: {
x: {
type: 'linear',
position: 'bottom'
}
},
plugins: {
tooltip: {
tooltip: {
enabled: false,
position: 'nearest',
external: externalTooltipHandler
}
}}}};
var output = false, finalData = [];
fetch("http://localhost:3000/getdata", {method: 'POST'})
.then(data => {return data.json()})
.then(data => {
//console.log(data);
const ctx = document.getElementById('myChart').getContext('2d');
const myChart = new Chart(ctx, config);
for (let i = 0; i<data.length; i++){
chartData.datasets[0].data.push({x:data[i].data.id, y: data[i].data.public_metrics.like_count})
myChart.update();
};
})
// Something along the lines of
//<blockquote class="twitter-tweet" data-theme="dark">
//
//</blockquote>
As the question says, I'd like to display the tooltip as the embedded tweet, showing when hovered over, I've tried reconfiguring the samples here https://www.chartjs.org/docs/latest/samples/tooltip/html.html and on other stackoverflow pages, though I can't get those to work.
what it would look like: https://i.stack.imgur.com/x79aT.png

ChartJs with try catch

So I'm trying to make a JS function that uses ChartJS, the variable/data the fucntion gets, is a JSON object. The reason why I use try/catch is because the two lines under here:
let labels = json_data.data.map(e => e.StartTime);
let data = json_data.data.map(e => e.StatusId);
Isn't always set if there is any data they are set, but if not is the only one set
let data = json_data.message.map(e => e.message);
Unless on page load, then nothing is set.
The JSON object change when a <Select> dropdown is changed, and if there is data in one then the canvas is loaded, but if the user then select one with no data, I want the graft to be empty/destroyed, but I cant do this because I'm in a try catch, and if I define it in the catch too, then it says that the ID already is in use. What do I have to do to "reset/destroy" it in the catch?
function chartJSLoad(json_data) {
try {
let labels = json_data.data.map(e => e.StartTime);
let data = json_data.data.map(e => e.StatusId);
console.log(labels);
console.log(data);
var ctx = document.getElementById('canvaschartjs').getContext('2d');
var myChart = new Chart(ctx, {
data: {
datasets: [{
type: 'bar',
label: 'Bar Dataset',
data: data,
backgroundColor: 'rgba(0, 150, 90)',
borderColor: 'rgba(0, 255, 90)',
order: 2
}, {
type: 'line',
label: 'Line Dataset',
data: data,
backgroundColor: 'rgba(150, 0, 90)',
borderColor: 'rgba(255, 0, 90)',
order: 1
}],
labels: labels
},
options: {
maintainAspectRatio: false,
responsive: true,
scales: {
x: {
stacked: true,
},
y: {
stacked: true
}
}
}
});
} catch (error) {
if (typeof json_data !== 'undefined') {
myChart.destroy();
alert(json_data.message);
}
}
}
You can use the static method getChart to check if a chart with that context already exists, if it does you get that chart instance which you can destroy:
catch (error) {
if (typeof json_data !== 'undefined') {
let chart = Chart.getChart('canvaschartjs');
if (typeof chart !== 'undefined') {
chart.destroy()
}
alert(json_data.message);
}
}
Live example:
var options = {
type: 'line',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
borderColor: 'pink'
},
{
label: '# of Points',
data: [7, 11, 5, 8, 3, 7],
borderColor: 'orange'
}
]
},
options: {}
}
var ctx = document.getElementById('chartJSContainer').getContext('2d');
let myChart = new Chart(ctx, options);
let chart = Chart.getChart('chartJSContainer');
if (typeof chart !== 'undefined') {
chart.destroy() // Does not show anything because of this line, comment it out to show again
}
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.6.0/chart.js"></script>
</body>

Chart.js glitches and reverts to previous dataset on hover

I am using Chart.js (https://www.chartjs.org) to make a chart, but after you switch the chart data to a new dataset and roll over the chart with the cursor it glitches out and reverts back to the old dataset. Here is my code:
<li class="breadcrumb-item"><select id="cityselect" onchange="changeCity();">
<option value="la">Los Angeles</option>
<option value="oc">Orange County</option>
<option value="sf">San Francisco</option>
</select></li>
<div class="bottommargin divcenter" style="max-width: 90%; min-height: 350px;">
<canvas id="resChart"></canvas>
</div>
function changeCity(){
var ctx = document.getElementById('resChart');
var resChart = new Chart(ctx);
resChart.destroy();
getResChartData();
}
function getResChartData() {
var city = document.getElementById("cityselect").value;
$.ajax({
type: 'GET',
url: 'getreschart.php',
dataType: 'json',
data: { city:city, },
success: function(response) {
//console.log (response);
function collate(d) {
return d.reduce(function(prev, cur, index) {
var ret = {};
for (var prop in cur) {
if (index === 0) {
ret[prop] = [];
} else {
ret[prop] = prev[prop];
}
ret[prop].push(cur[prop]);
}
return ret;
}, {});
}
var reduced = collate(response);
var ctx = document.getElementById('resChart').getContext('2d');
var resChart = new Chart(ctx, {
type: 'line',
data: {
labels: reduced.mmyy,
datasets: [{
label: 'Fulfilled Reservations',
data: reduced.fulfilledreservations,
backgroundColor: window.chartColors.orange,
borderColor: window.chartColors.orange,
fill: false
},
{
label: 'Unfulfilled Reservations',
data: reduced.unfulfilledreservations,
backgroundColor: window.chartColors.blue,
borderColor: window.chartColors.blue,
fill: false
},
{
label: 'All Reservations',
data: reduced.allreservations,
backgroundColor: window.chartColors.gray,
borderColor: window.chartColors.gray,
fill: false
}]
},
options: {
responsive: true,
elements: {
line: {
tension: 0 // disables bezier curves
}
}
}
});
}
});
}
As you can see I have destroyed the chart and I have updated it property (I think) - what gives?
we should use the
if(myChart)
myChart.destroy()
method before assigning new datasets as described in the following link
ChartJs line chart repaint glitch while hovering over

Inserting data from controller to an array in javascript

I try to create a graph using Chart.js and get the data from database, but I am confused how to pass the data to an array variable in view.
This is the Controller
public function ApiLaporanBulanan()
{
$data = DB::table("transaksipenjualan")->select(DB::raw('EXTRACT(MONTH FROM tanggaltransaksi) AS Bulan, SUM(total) as Pendapatan'))
->groupBy(DB::raw('EXTRACT(MONTH FROM tanggaltransaksi)'))
->get();
return response()->json($data);
//Accessing Data
dd($data[0]->Bulan);
}
This is the script in view
<script>
var url = "{{url('laporan/pendapatanAPI')}}";
var Bulan = [];
var Pendapatan = [];
$(document).ready(function(){
$.get(url, function(response){
response.forEach(function(data){
Bulan.push(data->Bulan);
Pendapatan.push(data->Pendapatan);
});
var ctx = document.getElementById("canvas").getContext('2d');
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: Bulan,
datasets: [{
label: 'Nilai Pendapatan',
data: Pendapatan,
borderWidth: 1
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero:true
}
}]
}
}
});
});
});
</script>
You can create two array in your controller.
$label = [];
$dataset = [];
and loop through your collection and push data to these arrays
foreach($data as $value){
$label[] = $value->data_field;
$dataset[] = $value->data_field;
}
And pass it to your blade and assign these array to your chart
...
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: Bulan,
datasets: [{
label: 'Nilai Pendapatan',// label data
data: Pendapatan, // dataset
borderWidth: 1
}]
},
....

Categories