Using Numeral.js to round JSON numbers in % - javascript

I am fetching json data from a API and I have to display some of the numbers as %. The json data displays them as 0.00. I tried this method, but it didn't work. I want to use a url to fetch my data, and then use Numeral.js to make the filtered data I got in %. What am I doing wrong? I create a template for my graph. I then make a fetch request to get my data and filter it, so I get the values I need. Then I take that value and try to format it. The new value I want to put on the graph.
const data = {
labels: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
datasets: [
{
label: "ADOPTION",
data: [18, 12, 6, 9, 12, 3, 9],
backgroundColor: "rgba(73, 117, 197, 1)",
borderColor: "rgba(73, 117, 197, 1)"
},
{
label: "Target",
data: [0.654, 0.654, 0.751],
backgroundColor: "rgba(236, 123, 46, 1)",
borderColor: "rgba(236, 123, 46, 1)"
}
]
};
// config for graph
const config = {
type: "line",
data: data,
options: {
plugins: {
title: {
display: true,
text: 'data'
},
},
scales: {
y: {
beginAtZero: true
}
}
}
};
// render init block
const myChart = new Chart(
document.getElementById("data"),
config
);
// Fethc block for the graph
async function fetchJSON() {
const url="link";
const response = await fetch(url);
//* loads waiting to complete the request
const datapoints = await response.json();
return datapoints;
}
fetchJSON().then((datapoints) => {
const month = datapoints.map(function (index) {
return index.PERIOD_NAME; //*reffers to jSon word from file
});
console.log(month);
myChart.config.data.labels = month;
myChart.update();
});
fetchJSON().then((datapoints) => {
const total = datapoints.map(function (index) {
return index.ADOPTION //*reffers to jSon word from file
});
var string = numeral(datapoints).format('0.000%');
console.log(string);
myChart.config.data.datasets[0].data = total;
myChart.update();
});
<div class="col-sm-12 col-md-4 col-lg-4">
<canvas id="data"></canvas>
</div>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/chart.js"></script>

I'm guessing datapoints is an array. Numeral takes numbers or strings that it trys to convert into a number. You can use datapoints.map(val => numeral(val).format('0.00%')) to format the datapoints elements.

Related

Set a limit / max number for legends

Lets say I have a Donut chart with 5 items in data like this
const data = {
labels: ['E-commerce', 'Enterprise', 'Green', 'Grey', 'Purple'],
datasets: [
{
label: '# of Votes',
data: [12, 19, 3, 5, 3],
backgroundColor: ['#C07CC3', '#9C3848', '#9DDBAD', '#ADA8B6', '#606EDA'],
borderWidth: 1,
},
],
}
I don't want it to show all the legends as I don't have space or whatever reason
How can I hide the Green and purple in this example?
I mean only from legends not from chart
I see two easy ways, how you could approach this problem:
(I personally I would use the second option below, it is more configurable, but it needs just abit of coding)
You can simply delete the labels you want to delete from the labels- array, and they won't show up in the legend.
But keep in mind you would have to change the order of the data and backgroundColor arrays, to match this change.
Here a short demo:
const data = {
labels: ['E-commerce', 'Enterprise', 'Grey'], // <-- just remove the unwanted labels
datasets: [{
data: [12, 19, 5, 3, 3], // <-- reorder
backgroundColor: ['#C07CC3', '#9C3848', '#ADA8B6', '#9DDBAD', '#606EDA'], // <-- reorder
borderWidth: 1,
}],
};
const config = {
type: 'doughnut',
data: data,
options: {
maintainAspectRatio: false,
plugins: {
legend: {
position: 'right',
labels: {
usePointStyle: true,
},
}
},
}
};
new Chart(
document.getElementById('chart'),
config
);
<script src="//cdn.jsdelivr.net/npm/chart.js"></script>
<div class="chart" style="height:184px; width:350px;">
<canvas id="chart" ></canvas>
</div>
Better and cleaner (but some coding is needed), you can filter out label-items, you don't want to display, with the function array filter. (details can be found in the documentation)
UPDATED Alternative Version Demo:
here only the Top 3 labels (limiting the amount of labels with the variable maxLabelsToShow) will be shown (sort order is descending, but changing this is would be easy)
function getLabelsOnlyTopX(num, data, labels){
let selectedLabels = []
//we don't want to alter the order
let helperData = [...data];
//sort in descending order
helperData.sort( (a,b) => b-a);
//get top X Values
helperData = helperData.slice(0, num);
//get index for the data
let indexes = data.map( (value, index) => ({value,index}) ).filter(item => helperData.some(n1 => n1 == item.value))
//slecet only labels with the correct index
selectedLabels = labels.filter((value, index) => indexes.some( n => n.index == index))
// just be sure that a maximum of num labels are sent
return selectedLabels.slice(0, num);
}
let maxLabelsToShow = 3;
let serverData = [12, 19, 3, 5, 3]
let labels = ['E-commerce', 'Enterprise', 'Green', 'Grey', 'Purple'];
// Calling the newly created function
let showOnly = getLabelsOnlyTopX(maxLabelsToShow, serverData, labels);
const data = {
labels: labels,
datasets: [{
data: serverData,
backgroundColor: ['#C07CC3', '#9C3848',
'#9DDBAD', '#ADA8B6', '#606EDA'],
borderWidth: 1,
}],
};
const config = {
type: 'doughnut',
data: data,
options: {
maintainAspectRatio: false,
plugins: {
legend: {
position: 'right',
labels: {
usePointStyle: true,
/* FILTER function */
filter: function(item, chart) {
return showOnly.indexOf( item.text) > -1;
}
},
}
},
}
};
new Chart(
document.getElementById('chart'),
config
);
<script src="//cdn.jsdelivr.net/npm/chart.js"></script>
<div class="chart" style="height:184px; width:350px;">
<canvas id="chart" ></canvas>
</div>

Can't display api data to a chart (Chartjs)

The chart it is showing only the fell information and marking the data numbers in datasets in the donut. What I am looking for is that the chart shows the values ​​of found and fell (from the api). I have tried to delete those parameters and change it but it is not reflected. also above the chart there are many small rectangles with the values ​​of found and fell
async function getMeteor() {
const url = 'https://data.nasa.gov/resource/gh4g-9sfh.json'
const result = await fetch(url)
const barChartData = await result.json()
const falling = barChartData.map( (x) => x.fall)
return falling;
}
async function printChart() {
const fallData = await getMeteor();
const data = {
labels: fallData,
datasets: [{
label: 'Fell Meteors',
backgroundColor: 'rgb(255, 99, 132)',
borderColor: 'rgb(255, 99, 132)',
data: [0, 10, 5, 2, 20, 30, 45],
}]
};
const config = {
type: 'doughnut',
data: data,
options: {}
};
const myChart = new Chart(
document.getElementById('myChart'),
config
);
}
printChart();
Try changing document.getElementById('myChart') to
document.getElementById('myChart').getContext('2d');

Chartjs using array in label field

I am making a simple bar chart using Chartjs 3.x
I make requests to a server to fetch json data and then store certain parts of it into arrays, here is the code for this:
serverData = JSON.parse(http.responseText);
console.log(serverData);
stundenProjekt = serverData.abzurechnen.nachProjekt.map((s) => {
return s.second.summe;
});
labelsP = serverData.abzurechnen.nachProjekt.map((p) => {
return p.first;
});
I then want to use these arrays in the data and label fields of the chart. I'm using stundenProjekt as data and it works fine, but when I use labelsP as label for the chart, it doesn't work. Here is the code of the chart:
const data = {
labels: labelsP,
datasets: [{
label: 'Projekte',
data: stundenProjekt,
backgroundColor: [
'#f4f40b',
],
borderColor: [
'#B1B101',
],
borderWidth: 3,
}]
};
if (barChartProjekt) {
data.datasets.forEach((ds, i) => {
barChartProjekt.data.datasets[i].data = ds.data;
barChartProjekt.labels = newLabelsArray;
})
barChartProjekt.update();
} else {
barChartProjekt = new Chart(chart, {
type: 'bar',
data: data,
options: {
responsive: true,
plugins: {
legend: {
labels: {
color: "white",
font: {
size: 18
}
}
}
},
scales: {
y: {
ticks: {
color: "white",
font: {
size: 18,
},
stepSize: 1,
beginAtZero: true
}
},
x: {
ticks: {
color: "white",
font: {
size: 14
},
stepSize: 1,
beginAtZero: true
}
}
}
}
});
}
The only workaround I have found is to copy the contents of labelsP and paste them in the label field. These are the contents of labelsP and how I did the workaround:
["nexnet-SB-Cloud", "AUTEC - PSK-System²", "Fritzsche", "nexnet-eBalance", "IfT - Neuentwicklung", "wattform", "Migration", "Fahrwerkregelkreis", "bmp greengas", "nexnet-SQL-Abfragen über API", "lambda9", "Nord Stadtwerke", "edifact", "SOLVIT", "BürgerGrünStrom", "SOLVCPM", "lambda captis", "SOLVEDI", "green city power", "max.power"]
const data = {
labels: ["nexnet-SB-Cloud", "AUTEC - PSK-System²", "Fritzsche", "nexnet-eBalance", "IfT - Neuentwicklung", "wattform", "Migration", "bmp greengas", "Fahrwerkregelkreis", "nexnet-SQL-Abfragen über API", "lambda9", "Nord Stadtwerke", "edifact", "SOLVIT", "BürgerGrünStrom", "SOLVCPM", "lambda captis", "SOLVEDI", "green city power", "max.power"],
datasets: [{
label: 'Projekte',
data: stundenProjekt,
backgroundColor: [
'#f4f40b',
],
borderColor: [
'#B1B101',
],
borderWidth: 3,
}]
};
In this way, the chart works and everything shows up as it should, however, I want to use it as shown in the first snippet of code, as labelsP gets updated every some seconds with new data extracted from the server. So, why is it that if I put labelsP alone in the label field it doesn't work, but if I copy and paste the contents of labelsP in the label field, it does work?
The problem is that you add the labels to the wrong position in the chart configuration.
Instead of...
barChartProjekt.labels = newLabelsArray;
try this...
barChartProjekt.data.labels = newLabelsArray;

How to get data of json file for chart.js diagram

I want to read a .json file and use its data for the data attribute of a chart.js diagram.
My code is as follows:
const test = []
fetch("./load.json")
.then(response => {
return response.json();
})
.then(data => {
// console.log(data)
for (i = 0; i < data.length; i++) {
// console.log(data[i])
test.push(data[i])
}
});
console.log(test)
// setup block
const data = {
datasets: [{
label: 'Sales',
data: test,
borderColor: 'rgba(234,124,234,0.4)',
backgroundColor: 'rgba(34,14,24,0.4)'
}]
};
// config block
const config = {
type: 'line',
data,
options: {
scales: {
x: {
type: 'time',
time: {
unit: 'second'
}
},
y: {
beginAtZero: true
},
xAxes: [{
type: "time",
time: {
min: 1628373600,
max: 1628460000
}
}]
}
}
};
// render / init block
const myChart = new Chart(
document.getElementById('myChart'),
config
);
My .json file:
[{"x": "2021-08-08T13:12:23", "y":3},
{"x": "2021-08-08T13:12:45", "y":5},
{"x": "2021-08-08T13:12:46", "y":6},
{"x": "2021-08-08T13:13:11", "y":3},
{"x": "2021-08-08T13:14:23", "y":9},
{"x": "2021-08-08T13:16:45", "y":1}]
I have tried to parse the data from the .json file and in console it shows up but I think the data attribute of chart.js is not able to read the data in the test variable.
Does somebody know how to do this?
Seems like the chart is being made before the data is ready since loading the json is an async proces, you can either instantiate the chart in your second .then when the data is available or create the chart as you do and then in the second .then update the data in the chart and call the update method

Changing chart data dynamically with C# from SQL database

This is my chart code.
<!-- Graphs -->
<script src="../Scripts/Chart.min.js"></script>
<script>
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
datasets: [{
data: [1, 6, 2, 5, 9, 5, 6],
label: "Issues Resolved",
lineTension: 0,
backgroundColor: 'transparent',
borderColor: '#007bff',
borderWidth: 4,
pointBackgroundColor: '#007bff'
}, {
data: [8, 5, 8, 6, 0, 2, 2],
label: "Issues Raised",
lineTension: 0,
backgroundColor: 'transparent',
borderColor: '#ff8400',
borderWidth: 4,
pointBackgroundColor: '#ff8400'
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: false
}
}]
},
legend: {
display: true
},
title: {
display: true,
text: 'Issues Raised VS Issues Resolved'
}
}
});
</script>
This graph, though working fine, is static. What I want to ask is whether I can dynamically change the data (of which I'll always have 7 values, for each day of the week) in my datasets (of which I'll always have 2 values, for issues raised and issues resolved) from my .aspx.cs (which will get this data from my SQL Database) at runtime. And if so, how?
Thank you for your help.
I had a similar issue and found this solution. This solution requires you to use using System.Web.Services; and I will leave it to you to implement access to your SQL Database. But hopefully this solution can help you too!
Try using the following in the .ASPX file:
<!-- Graphs -->
<script src="../Scripts/Chart.min.js"></script>
<script>
$(function () {
$.ajax({
type: 'POST',
dataType: 'json',
contentType: 'application/json',
url: 'BackendFileName.aspx/GetChartData', // change to your .aspx filename
data: '{}',
success: function (response) {
drawChart(response.d);
},
error: function () {
console.error("Error loading data! Please try again.");
}
});
})
function drawChart(dataValues) {
var issuesResolved = [];
var issuesRaised = [];
for (var i = 0; i < dataValues.length; i++) {
issuesResolved[i] = dataValues[i].issuesResolved;
issuesRaised[i] = dataValues[i].issuesRaised;
}
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
datasets: [{
data: issuesResolved,
label: "Issues Resolved",
lineTension: 0,
backgroundColor: 'transparent',
borderColor: '#007bff',
borderWidth: 4,
pointBackgroundColor: '#007bff'
}, {
data: issuesRaised,
label: "Issues Raised",
lineTension: 0,
backgroundColor: 'transparent',
borderColor: '#ff8400',
borderWidth: 4,
pointBackgroundColor: '#ff8400'
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: false
}
}]
},
legend: {
display: true
},
title: {
display: true,
text: 'Issues Raised VS Issues Resolved'
}
}
});
}
</script>
Then add the following methods within backend file:
// Arbitrary class to hold required data from SQL Database
public class ChartDetails
{
public string IssuesResolved { get; set; }
public string IssuesRaised { get; set; }
public ChartDetails()
{
}
}
// Method that will be called by JQuery script
[WebMethod]
public static List<ChartDetails> GetChartData()
{
List<ChartDetails> dataList = new List<ChartDetails>();
// Access SQL Database Data
// Assign SQL Data to List<ChartDetails> dataList
return dataList;
}
You most certainly can. Take a look at the documentation here, you just need to implement the AJAX polling to see if the source dataset has changed.
I believe what you can do is:
Create a class level string variable in your code behind for holding the serialized array like
protected string weeklyData;
In Page_Load eventhandler, fetch the data from SQL database and populate an array of numbers int or decimal or floats depending upon your stored data. Lets say you end up with an array containing data
int[] data = [8, 5, 8, 6, 0, 2, 2];
Use the JavaScriptSerializer class to serialize it into a string and assign to weeklyData class variable like this:
JavaScriptSerializer serializer = new JavaScriptSerializer();
weeklyData = serializer.Serialize(data);
Assign weeklyData variable in your chart initialization code like:
data: <%= weeklyData %>,
enter code here
Another better option will be to write a WEB API service which will expose an endpoint for fetching the weekly data in json array format. Then, you can use jquery get method to get data and then initialize chart
$.get('{enpointurl}', function(weeklyData) {
//Write chart initialization code here and pass weekly data to chart data option
});
Add a hidden field:
<asp:HiddenField ID="hdnLabels" runat="server" Value="" />
<asp:HiddenField ID="hdnData" runat="server" Value="" />
In your chart script add:
labels: [<%= hdnLabels.Value %>],
datasets: [
{
data: [ <%= hdnData.Value %>],
... other options here,
}
]
In code behind:
public void ShowChartData()
string _data = "";
string _labels = "";
......Loop your SqlDataReader
....
....
while (dr.Read())
{
_labels = _data + dr["DayOfWeek"].ToString() + #",";
_data = _data + dr["DayOfWeekValue"].ToString() + #",";
}
_labels = _label.Remove(_label.Length - 1);
_data = _data.Remove(_data.Length - 1);
hdnLabels.Value = _labels;
hdnData.Value = _data;
}
Hope this helps...

Categories

Resources