I cant save my highchart chart data in localStorage - javascript

I cant save data in localstorage, I get the result [object Object],[object Object],[object Object]
Here is the code
var usersonline = null;
var maxonline = 50;
Highcharts.stockChart('container', {
chart: {
events: {
load: function () {
// set up the updating of the chart each second
var series = this.series[0];
setInterval(function () {
var x = (new Date()).getTime(), // current time
y = Math.round(usersonline);
series.addPoint([x, y], true, false);
}, 1000);
}
}
},
time: {
useUTC: false
},
rangeSelector: {
buttons: [{
count: 1,
type: 'hour',
text: '1H'
}, {
count: 3,
type: 'hour',
text: '3H'
}, {
type: 'all',
text: 'All'
}],
inputEnabled: false,
selected: 2
},
title: {
text: 'Live Chart of Players Online'
},
exporting: {
enabled: false
},
yAxis: {
title: 'Players Online',
min: 0,
plotLines: [{
color: 'red', // Color value
label: {
text: "Max Player Line"
},
value: maxonline, // Value of where the line will appear
width: 2 // Width of the line
}]
},
series: [{
name: 'Players Online',
connectNulls: false,
data: (function () {
var data = [],
time = (new Date()).getTime(),
i;
if (typeof(Storage) !== "undefined") {
if (localStorage.getItem("chartdata") === null) {
localStorage.setItem('chartdata',[])
data = []
console.log("No Data Found, Creating Some!")
} else {
data = JSON.parse(localStorage.getItem('chartdata'))
console.log("Chart Data Loaded.")
}
} else {
console.log("localStorage is not Supported. Saving Chart Data will not work.")
}
// generate an array of random data
window.onbeforeunload = function(){
console.log("Chart data Saved")
localStorage.chartdata = JSON.stringify(data)
}
return data;
}())
}],
lang: {
noData: "No Data."
},
noData: {
style: {
fontWeight: 'bold',
fontSize: '40px',
color: '#303030'
}
}
});
If I refresh the page it shows the chart as blank and It doesnt display "No Data" so there is data there but it is broken. What I want to happen is When I refresh the page it will keep the data, even when the browser or computer gets restarted.
Is there any solution to this problem, I tried multiple ways but none of them work.
This is a live data chart that I need to save data so The Chart doesnt go blank if you accidently refresh the page.

So the reason why when you get the item it says [Object object] is because localStorage.setItem accepts a DOMString, not an object. setItem will use toString to coerce values into a string, and Object.prototype.toString will always be [object Object].
https://developer.mozilla.org/en-US/docs/Web/API/Storage/setItem
You need to use JSON.stringify to convert your array into a valid JSON string in your localStorage.setItem function call and then use JSON.parse to parse that string when you use localStorage.getItem.
const loki = { "type": "dog", "name": "Loki" }
// Sets [object Object] in local storage
localStorage.setItem("lokiKey", loki)
// Sets "{"type":"dog","name":"Loki"}" in local storage
localStorage.setItem("lokiKey", JSON.stringify(loki))
Hope this helps!

Did you try to use myChart.addSeries ? If Series have been changed you should calling method redraw

Related

Chart.js, returning an "date" array to plot the line graph

in the database I have 3 data which i send via Rest-API to the Frontend Angular.
This works fine.
Here in browser console, you can see all three dataset, which I get through node.js via Rest-API:
How it looks in the browser console
the result in the browser console looks like this:
0:
device_id: 2885679
list: Array(1)
0:
dt: 1596608643
main:
humidity: 10
pressure: 7.86
temp: 120.052
temp_max: 40.052
temp_min: 20.052
__proto__: Object
__proto__: Object
length: 1
__proto__: Array(0)
message: "1"
__v: 0
_id: "5f2a63857ce17d64d49465a4"
In the typescript component xy.component.ts my code looks like this:
export class ContactsComponent {
chart: any = [];
constructor(private contactService: ContactService) { }
ngOnInit() {
this.contactService.getContacts()
.subscribe((res: any[]) => {
console.log(res);
for (let i = 0; i < res.length; i++) {
let temp_max = res[i]['list'].map(res => res.main.temp_max);
let temp_min = res[i]['list'].map(res => res.main.temp_min);
let alldates = res[i]['list'].map(res => res.dt)
console.log(alldates)
let deviceData = []
alldates.forEach((res) => {
let jsdate = new Date(res * 1000)
deviceData.push(jsdate.toLocaleTimeString('en', { year: 'numeric', month: 'short', day: 'numeric' }))
})
console.log(deviceData)
this.chart = new Chart('canvas', {
type: 'line',
data: {
labels: deviceData,
datasets: [{
data: temp_max,
borderColor: '#3cba9f',
fill: false
}, {
data: temp_min,
borderColor: '#ffcc00',
fill: false
},
]
},
options: {
legend: {
display: false
},
scales: {
xAxes: [{
display: true
}],
yAxes: [{
display: true
}]
}
}
})
}
})
}
Why console.log(deviceData) only return the last value of the iteration?
I want to return all the values in console.log(devicedata) to draw a graph based on 3 timestamps. Here when I only get back 1 timestamp. Somehow it overwrites the values with the deviceData.push - Methode.
My goal is to draw all the datapoints i have (refer to the screenshots of the browser console).
Here how the graph is plot in the browser. It only plots one point, that is exactly the point of the console.log(deviceData):
graph
What is the problem and how can I fix it?
Thanks
Eden
It seems every object in res has a list with only a single item.
(res[i]['list'] is an array of length 1)
Try logging this:
(this takes all the values of each item and puts them in a single list)
let allvalues = [];
for (const item of res) {
for (const measurement of item.list) {
allvalues.push(measurement)
}
}
console.log(allvalues);

Updating Div with Total Records Outside of table

I’m working with datatables and trying to figure out what I’m doing wrong. I am trying to display the total number of rows when the table hits the draw event on the table. Right now with the code, I’m showing below I am not getting any console errors. The element where the number is supposed to be updated is correct. I am just not getting it to render with the correct count.
("use strict");
const renderStatusCell = (data, type, full, meta) => {
const status = {
0: { title: "Inactive" },
1: { title: "Active" }
};
if (typeof status[data] === "undefined") {
return data;
}
return status[data].title;
};
var table = $('[data-table="users.index"]');
// begin first table
table.DataTable({
// Order settings
order: [[1, "desc"]],
ajax: "/titles",
columns: [
{ data: "id", title: "User ID" },
{ data: "name", title: "Name" },
{ data: "slug", title: "Slug" },
{ data: "introduced_at", title: "Date Introduced" },
{ data: "is_active", title: "Status", render: renderStatusCell },
{
data: "action",
title: "Actions",
orderable: false,
responsivePriority: -1
}
]
});
var updateTotal = function() {
table.on("draw", function() {
$("#kt_subheader_total").html(table.fnSettings().fnRecordsTotal());
});
};
I expected when the table was rendered to update the dom with the correct number of rows however the div does not get updated.
I don't understand your problem, but I think you need something like that.
table
.row($(this).parents('tr'))
.remove()
.draw();
or
table.ajax.reload();
I believe you need to wait until the HTML loads before running all your javascript code. Also, if you are storing the total, you not make it a function but rather just store the value.
'use strict';
// this will make sure all the HTML loads before the JavaScript runs.
$(function() {
var table = $('[data-table="users.index"]');
var updateTotal = null; // store in a variable
const renderStatusCell = (data, type, full, meta) => {
const status = {
0: { title: "Inactive" },
1: { title: "Active" }
};
if (typeof status[data] === "undefined")
return data;
return status[data].title;
};
// begin first table
table.DataTable({
// Order settings
order: [[1, "desc"]],
ajax: "/titles",
columns: [
{ data: "id", title: "User ID" },
{ data: "name", title: "Name" },
{ data: "slug", title: "Slug" },
{ data: "introduced_at", title: "Date Introduced" },
{ data: "is_active", title: "Status", render: renderStatusCell },
{
data: "action",
title: "Actions",
orderable: false,
responsivePriority: -1
}
]
});
table.on("draw", function() {
updateTotal = table.fnSettings().fnRecordsTotal();
$("#kt_subheader_total").html(table.fnSettings().fnRecordsTotal());
});
});

highcharts doesn't read data, works with fake data

I'm trying to make visualization of the voltage, Array has 1k elements but I'm testing it on first 10 for now, the thing is that It doesn't display anything, what's more interesting when I use fake date which is commented out now, It shows chart properly. I thought that perhaps there is some problem with array so tried to use Array.from but it also brought no effect, here is my code:
.then(function(res) {
var averageVoltage = []
var inputVoltage = []
var date = []
for (var i = 0; i < 10; i++) {
if (res[i].average_volatage !== undefined) {
averageVoltage.push(res[i].average_volatage)
date.push(res[i].timestamp)
}
}
console.log(averageVoltage)
console.log(date)
Highcharts.chart('battery_chart', {
chart: {
type: 'line'
},
title: {
text: id
},
yAxis: {
title: {
text: 'Measurement'
},
},
xAxis: {
categories: date
},
series: [{
name: 'Average Voltage',
data: averageVoltage
// data: [12283, 12283, 12281, 12280, 12282, 12283, 12281, 12282, 12281, 12280]
},
]
});
and that's how array is shown in console.log:
Your array should show up as [12283, 12281, 12280, etc.] in console as well, instead it shows up as [Number, Number, ...]. Try changing this line:
averageVoltage.push(res[i].average_volatage)
to:
averageVoltage.push(parseInt(res[i].average_volatage))
Additionally, instead of using dates as categories, it could be easier to use the highchart datetime axis. This would let you manipulate how you want the date displayed, have several series with different timestamps in one graph, and many other things. To get this to work, you could do this:
.then(function(res) {
var averageVoltage = []
var inputVoltage = []
for (var i = 0; i < 10; i++) {
if (res[i].average_volatage !== undefined) {
averageVoltage.push({x: new Date(res[i].timestamp).getTime(), y: parseInt(res[i].average_volatage)})
}
}
console.log(averageVoltage)
Highcharts.chart('battery_chart', {
chart: {
type: 'line'
},
title: {
text: id
},
yAxis: {
title: {
text: 'Measurement'
},
},
xAxis: {
type: 'datetime'
},
series: [{
name: 'Average Voltage',
data: averageVoltage
},
]
});

Javascript : ""Uncaught TypeError: Cannot read property 'x' of undefined"" in canvasjs.min.js

I am trying to get a bar chart from my JSON using javascript but receiving below error message :
Uncaught TypeError: Cannot read property 'x' of undefined
at q._processMultiseriesPlotUnit (canvasjs.min.js:200)
at q._processData (canvasjs.min.js:197)
at q.render (canvasjs.min.js:181)
at XMLHttpRequest.xhttp.onreadystatechange (Dashboard.js:36)
Below is my javascript and JSON:
function orderchart(){
xhttp = new XMLHttpRequest();
xhttp.open("GET", "/getOrderDetails", true);
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhttp.send();
xhttp.onreadystatechange = function() {
if ((xhttp.readyState == 4) && (xhttp.status == 200)) {
var jsonResponse = JSON.parse(xhttp.responseText);
var ordercount=jsonResponse.map(function(e) {
return e.ordercount;
});
var season=jsonResponse.map(function(e) {
return e.season;
});
console.log(ordercount,season);
var chart = new CanvasJS.Chart("chartContainer", {
animationEnabled: true,
theme: "light2", // "light1", "light2", "dark1", "dark2"
axisX:{
interval: 1
},
axisY2:{
title: "Total Orders"
},
data: [{
type: "bar",
axisYType: "secondary",
dataPoints:{ y: ordercount, label:season },
}]
});
chart.render();
}
}
}
JSON:
[
{
"season": "Thanksgiving",
"ordercount": "15000"
},
{
"season": "Christmas",
"ordercount": "300000"
},
{
"season": "Newyear",
"ordercount": "100000"
}
]
My expected bar chart is :
I am getting this chart when I am manually passing values for datapoints but getting errors when trying to process it from JSON data.
I have noticed dumb error in my code which is a missing square parentheses in the datapoints. I have corrected that one like below,
data: [{
type: "bar",
axisYType: "secondary",
dataPoints:[{ y: ordercount, label:season },]
}]
But still not getting the expected graph,
Try this and you will get result:
window.onload = function () {
var data = [
{
"season": "Thanksgiving",
"ordercount": "15000"
},
{
"season": "Christmas",
"ordercount": "300000"
},
{
"season": "Newyear",
"ordercount": "100000"
}
]
var seasondata = []
for (let index = 0; index < data.length; index++) {
const element = data[index];
seasondata.push({label: data[index]["season"], y:Number(data[index]["ordercount"])})
}
var chart = new CanvasJS.Chart("chartContainer", {
title:{
text: "My First Chart in CanvasJS"
},
data: [
{
// Change type to "doughnut", "line", "splineArea", etc.
type: "bar",
dataPoints: seasondata
}
]
});
chart.render();
}
Put your json data into variable and then create and array and then place that into datapoints Your order count is string so convert that into number and it will work.
You can also check the result here in this link:
Working Example

How can I use json Data inside of my component state invalid when trying to use said data inside a variable?

I am trying to take the data I place into my state and then use portions of said data in the config variable so I can then render this data onto highCharts. However, I keep getting errors saying that "Cannot read property 'SeriesDates' of undefined, and etc for any other data from my json call. However, when I console log the state, the data is clearly in the state. The question is why can't I use it inside the config variable and how do I get it as values inside the variable? I am able to use data from my redux state easily ({this.props.stock.Name}) but the same is not true for the output from my json call.
import React, { Component } from 'react';
import { connect } from 'react-redux';
import ReactHighcharts from 'react-highcharts';
class StockChart extends Component {
constructor(props) {
super(props);
this.state = {chart: []};
}
componentDidMount() {
this.ChartData();
}
ChartData() {
return $.getJSON(`http://dev.markitondemand.com/MODApis/Api/Timeseries/json?symbol=${this.props.stock.Symbol}`)
.then((data) => {
var raw = JSON.stringify(data);
var json = JSON.parse(raw);
this.setState({ chart: json });
console.log(this.state);
});
}
render() {
const config = {
title: {
text: `${this.props.stock.Name}`,
x: -20 //center
},
subtitle: {
text: `${this.props.stock.Symbol}`,
x: -20
},
xAxis: {
categories: `${this.state.chart.Data.SeriesDates}`
},
yAxis: {
title: {
text: 'Price'
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}]
},
tooltip: {
valueSuffix: '$'
},
series: [{
name: 'AAPL',
data: `${this.state.chart.Data.close.values}`
}]
};
if (!this.props.stock) {
return <div></div>
}
return (
<div>
<ReactHighcharts config={config}></ReactHighcharts>
</div>
);
}
}
function mapStateToProps(state) {
return {
stock: state.selectedStock
};
}
If you take a close look into your code you are setting state after the component is mount. According to the react component lifecycle componentDidMount triggers after the first render. so at the time of render you will have empty chart state. i.e. this.state.chart.Data = undefined. so your code this.state.chart.Data.SeriesDates will throw the above error.
Note: since you are fetching data from server even though you put logic in componentWillMount it will through same error because fetching data from server takes time.
There could be two ways to solve the problem:
To set the initial state to some default values referring to the format of data that is returned
this.state = {chart: {
Data: {
SeriesData: {},
close: {},
...
}
}
};
OR
2. check for undefined in the render method.
const Data = this.state.chart.Data;
if(Data){
const config = {
title: {
text: `${this.props.stock.Name}`,
x: -20 //center
},
subtitle: {
text: `${this.props.stock.Symbol}`,
x: -20
},
xAxis: {
categories: `${this.state.chart.Data.SeriesDates}`
},
yAxis: {
title: {
text: 'Price'
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}]
},
tooltip: {
valueSuffix: '$'
},
series: [{
name: 'AAPL',
data: `${this.state.chart.Data.close.values}`
}]
};
}
Good Luck.

Categories