Ngx-Charts show all x axis values but alternate x-axis labels - javascript

I am currently working on ngx charts, for examples i have 12 x-axis every values need to be plotted in graph, but only alternate x-axis label need to be displayed.
html code
<ngx-charts-area-chart [view]="view" [scheme]="colorScheme" [legend]="legend" [showXAxisLabel]="showXAxisLabel" [showYAxisLabel]="showYAxisLabel" [xAxis]="xAxis" [yAxis]="yAxis"
[xAxisLabel]="xAxisLabel" [yAxisLabel]="yAxisLabel" [results]="multi" (select)="onSelect($event)">
</ngx-charts-area-chart>
data.ts
var multi = [ {
"name": "Belarus",
"series": [
{
"value": 5776,
"name": "Jan 19"
},
{
"value": 4299,
"name": "Feb 19"
},
{
"value": 3995,
"name": "Mar 19"
},
{
"value": 6597,
"name": "Apr 19"
},
{
"value": 4954,
"name": "May 19"
},
{
"name": "June 19",
"value": 3865
},
{
"name": "July 19",
"value": 2349
},
{
"name": "Aug 19",
"value": 6910
},
{
"name": "Sept 19",
"value": 6224
},
{
"name": "Oct 19",
"value": 4161
},
{
"name": "Nov 19",
"value": 4825
},
{
"name": "Dec 19",
"value": 3835
}
]},{
"name": "Croatia",
"series": [
{
"value": 2576,
"name": "Jan 19"
},
{
"value": 5427,
"name": "Feb 19"
},
{
"value": 3097,
"name": "Mar 19"
},
{
"value": 4385,
"name": "Apr 19"
},
{
"value": 4849,
"name": "May 19"
},
{
"name": "June 19",
"value": 2867
},
{
"name": "July 19",
"value": 6241
},
{
"name": "Aug 19",
"value": 6517
},
{
"name": "Sept 19",
"value": 3808
},
{
"name": "Oct 19",
"value": 2068
},
{
"name": "Nov 19",
"value": 5121
},
{
"name": "Dec 19",
"value": 3876
}
]}]
In the above data set in x-axis I need to plot all values in the graph but only alternate labels need to displayed. This need to be applied for all types of ngx charts.

Related

Recharts: Bar Chart Grouped on XAxis with LineChart on seperate XAxis (different data)

I have a barchart displaying groups of bars for each month in a 3 month period.
I have now been asked to add a line chart with the daily views spanning the 3 month period to chart like this (the red line i've drawn in the below image is the linechart of views):
I have tried several strategies, and all of them were unsuccessful. I'm currently at a loss to how i should approach this, and any ideas are appreciated. if worse comes to worse, i can always render two seperate charts and absolutely position one above the other, but i thought i'd try here for suggestions before resorting to that. I am not above changing my data structure, so long as i can keep the bar's grouped by month, and plot the line linearly over the 3 month period
The data structure i am currently using is something like below:
[
[
{
"month": "May",
"messages": {
"name": "messages",
"growth": 3,
"value": 35
},
"views": {
"name": "views",
"growth": 13,
"value": 61
},
"shares": {
"name": "shares",
"growth": 17,
"value": 193
},
"favorites": {
"name": "favorites",
"growth": 12,
"value": 164
}
},
{
"month": "June",
"messages": {
"name": "messages",
"growth": 22,
"value": 203
},
"views": {
"name": "views",
"growth": 6,
"value": 31
},
"shares": {
"name": "shares",
"growth": 21,
"value": 231
},
"favorites": {
"name": "favorites",
"growth": 19,
"value": 30
}
},
{
"month": "July",
"messages": {
"name": "messages",
"growth": 16,
"value": 196
},
"views": {
"name": "views",
"growth": 16,
"value": 107
},
"shares": {
"name": "shares",
"growth": 13,
"value": 59
},
"favorites": {
"name": "favorites",
"growth": 2,
"value": 175
}
}
],
[
{
"month": "May",
"messages": {
"name": "messages",
"growth": 20,
"value": 25
},
"views": {
"name": "views",
"growth": 21,
"value": 104
},
"shares": {
"name": "shares",
"growth": 14,
"value": 124
},
"favorites": {
"name": "favorites",
"growth": 1,
"value": 164
}
},
{
"month": "June",
"messages": {
"name": "messages",
"growth": 10,
"value": 168
},
"views": {
"name": "views",
"growth": 16,
"value": 128
},
"shares": {
"name": "shares",
"growth": 14,
"value": 79
},
"favorites": {
"name": "favorites",
"growth": 8,
"value": 187
}
},
{
"month": "July",
"messages": {
"name": "messages",
"growth": 21,
"value": 136
},
"views": {
"name": "views",
"growth": 9,
"value": 241
},
"shares": {
"name": "shares",
"growth": 20,
"value": 29
},
"favorites": {
"name": "favorites",
"growth": 0,
"value": 56
}
}
],
[
{
"month": "May",
"messages": {
"name": "messages",
"growth": 7,
"value": 212
},
"views": {
"name": "views",
"growth": 19,
"value": 90
},
"shares": {
"name": "shares",
"growth": 6,
"value": 175
},
"favorites": {
"name": "favorites",
"growth": 6,
"value": 66
}
},
{
"month": "June",
"messages": {
"name": "messages",
"growth": 8,
"value": 179
},
"views": {
"name": "views",
"growth": 12,
"value": 81
},
"shares": {
"name": "shares",
"growth": 9,
"value": 200
},
"favorites": {
"name": "favorites",
"growth": 2,
"value": 236
}
},
{
"month": "July",
"messages": {
"name": "messages",
"growth": 10,
"value": 200
},
"views": {
"name": "views",
"growth": 4,
"value": 105
},
"shares": {
"name": "shares",
"growth": 17,
"value": 188
},
"favorites": {
"name": "favorites",
"growth": 8,
"value": 77
}
}
],
[
{
"month": "May",
"messages": {
"name": "messages",
"growth": 17,
"value": 148
},
"views": {
"name": "views",
"growth": 16,
"value": 152
},
"shares": {
"name": "shares",
"growth": 24,
"value": 79
},
"favorites": {
"name": "favorites",
"growth": 12,
"value": 129
}
},
{
"month": "June",
"messages": {
"name": "messages",
"growth": 17,
"value": 202
},
"views": {
"name": "views",
"growth": 3,
"value": 132
},
"shares": {
"name": "shares",
"growth": 15,
"value": 186
},
"favorites": {
"name": "favorites",
"growth": 15,
"value": 105
}
},
{
"month": "July",
"messages": {
"name": "messages",
"growth": 11,
"value": 83
},
"views": {
"name": "views",
"growth": 19,
"value": 192
},
"shares": {
"name": "shares",
"growth": 6,
"value": 114
},
"favorites": {
"name": "favorites",
"growth": 2,
"value": 109
}
}
],
[
{
"month": "May",
"messages": {
"name": "messages",
"growth": 9,
"value": 104
},
"views": {
"name": "views",
"growth": 24,
"value": 54
},
"shares": {
"name": "shares",
"growth": 17,
"value": 60
},
"favorites": {
"name": "favorites",
"growth": 1,
"value": 108
}
},
{
"month": "June",
"messages": {
"name": "messages",
"growth": 6,
"value": 80
},
"views": {
"name": "views",
"growth": 22,
"value": 214
},
"shares": {
"name": "shares",
"growth": 23,
"value": 38
},
"favorites": {
"name": "favorites",
"growth": 15,
"value": 156
}
},
{
"month": "July",
"messages": {
"name": "messages",
"growth": 21,
"value": 247
},
"views": {
"name": "views",
"growth": 16,
"value": 72
},
"shares": {
"name": "shares",
"growth": 17,
"value": 158
},
"favorites": {
"name": "favorites",
"growth": 12,
"value": 74
}
}
],
[
{
"month": "May",
"messages": {
"name": "messages",
"growth": 2,
"value": 193
},
"views": {
"name": "views",
"growth": 6,
"value": 250
},
"shares": {
"name": "shares",
"growth": 18,
"value": 167
},
"favorites": {
"name": "favorites",
"growth": 20,
"value": 98
}
},
{
"month": "June",
"messages": {
"name": "messages",
"growth": 25,
"value": 84
},
"views": {
"name": "views",
"growth": 21,
"value": 212
},
"shares": {
"name": "shares",
"growth": 0,
"value": 172
},
"favorites": {
"name": "favorites",
"growth": 14,
"value": 246
}
},
{
"month": "July",
"messages": {
"name": "messages",
"growth": 14,
"value": 90
},
"views": {
"name": "views",
"growth": 6,
"value": 47
},
"shares": {
"name": "shares",
"growth": 7,
"value": 234
},
"favorites": {
"name": "favorites",
"growth": 14,
"value": 181
}
}
],
[
{
"month": "May",
"messages": {
"name": "messages",
"growth": 10,
"value": 140
},
"views": {
"name": "views",
"growth": 1,
"value": 112
},
"shares": {
"name": "shares",
"growth": 20,
"value": 191
},
"favorites": {
"name": "favorites",
"growth": 12,
"value": 58
}
},
{
"month": "June",
"messages": {
"name": "messages",
"growth": 2,
"value": 250
},
"views": {
"name": "views",
"growth": 14,
"value": 109
},
"shares": {
"name": "shares",
"growth": 16,
"value": 159
},
"favorites": {
"name": "favorites",
"growth": 12,
"value": 89
}
},
{
"month": "July",
"messages": {
"name": "messages",
"growth": 24,
"value": 46
},
"views": {
"name": "views",
"growth": 6,
"value": 189
},
"shares": {
"name": "shares",
"growth": 11,
"value": 197
},
"favorites": {
"name": "favorites",
"growth": 19,
"value": 179
}
}
],
[
{
"month": "May",
"messages": {
"name": "messages",
"growth": 19,
"value": 52
},
"views": {
"name": "views",
"growth": 11,
"value": 86
},
"shares": {
"name": "shares",
"growth": 2,
"value": 63
},
"favorites": {
"name": "favorites",
"growth": 17,
"value": 133
}
},
{
"month": "June",
"messages": {
"name": "messages",
"growth": 9,
"value": 225
},
"views": {
"name": "views",
"growth": 1,
"value": 68
},
"shares": {
"name": "shares",
"growth": 23,
"value": 220
},
"favorites": {
"name": "favorites",
"growth": 7,
"value": 124
}
},
{
"month": "July",
"messages": {
"name": "messages",
"growth": 9,
"value": 171
},
"views": {
"name": "views",
"growth": 1,
"value": 221
},
"shares": {
"name": "shares",
"growth": 22,
"value": 191
},
"favorites": {
"name": "favorites",
"growth": 4,
"value": 95
}
}
]
]
And the code for rendering my chart is:
import React from 'react';
import {
BarChart, Bar, XAxis, YAxis,
Tooltip, LabelList, Legend, ResponsiveContainer
} from 'recharts';
const labels = {
messages:'Messages',
views:'Views',
shares:'Shares',
favorites:'Favorites'
};
const legendFormatter = (value,entry,index) => labels[value.split('.')[0]];
const tooltipFormatter = (value,name,props) => [value,legendFormatter(name)]
const renderCustomizedLabel = (fill) =>{
return (props) => {
const { x, y, width, value } = props;
console.log(props)
return (
<g>
<rect width={width} height={30} x={x} y={y-30} fill="#fff" />
<text x={x + width / 2} y={y - 12} fill={fill} textAnchor="middle" dominantBaseline="middle">
{value > 0 ?('+'+value):value}
</text>
</g>
);
};
};
const RenderChart = ({data})=>(<ResponsiveContainer height={400}>
<BarChart data={data}
style={{ backgroundColor:'#F4F4F4' }}
margin={{ top: 45, right: 20, left: -10, bottom: 15 }}
>
<XAxis dataKey="month" />
<YAxis/>
<Tooltip formatter={tooltipFormatter} />
<Legend formatter={legendFormatter} />
<Bar dataKey="messages.value" fill="#4A8A95" minPointSize={5}>
<LabelList dataKey="messages.growth" content={renderCustomizedLabel('#4A8A95')} />
</Bar>
<Bar dataKey="views.value" fill="#FBBE52" minPointSize={5}>
<LabelList dataKey="views.growth" content={renderCustomizedLabel('#FBBE52')} />
</Bar>
<Bar dataKey="shares.value" fill="#EA4646" minPointSize={5}>
<LabelList dataKey="shares.growth" content={renderCustomizedLabel('#EA4646')} />
</Bar>
<Bar dataKey="favorites.value" fill="#0467BA" minPointSize={5}>
<LabelList dataKey="favorites.growth" content={renderCustomizedLabel('#0467BA')} />
</Bar>
</BarChart>
</ResponsiveContainer>);

I keep getting null values after adding new element to my object

I have an array object with some similar values. I'm excluding their duplicate values using a loop, and then I add the values to my other object(objectProperties) it's working fine however I get a NULL values inside category
// data which im extracting
var data = [
{
"label":"May 14",
"value":56714.4,
"proID":"ISB"
},
{
"label":"May 14",
"value":15902.5,
"proID":"LI8"
},
{
"label":"May 14",
"value":419.6,
"proID":"TR2"
},
{
"label":"May 15",
"value":2754.8,
"proID":"DAC"
},
{
"label":"May 15",
"value":50845.7,
"proID":"ISB"
},
{
"label":"May 15",
"value":19760.3,
"proID":"LI8"
},
{
"label":"May 15",
"value":1704.1,
"proID":"TR2"
},
{
"label":"May 16",
"value":2145.6,
"proID":"DAC"
},
{
"label":"May 16",
"value":55666.4,
"proID":"ISB"
},
{
"label":"May 16",
"value":15044.4,
"proID":"LI8"
},
{
"label":"May 16",
"value":2413.5,
"proID":"TR2"
},
{
"label":"May 17",
"value":6564.4,
"proID":"DAC"
},
{
"label":"May 17",
"value":71379,
"proID":"ISB"
},
{
"label":"May 17",
"value":21774.2,
"proID":"LI8"
},
{
"label":"May 17",
"value":2191.4,
"proID":"TR2"
},
{
"label":"May 18",
"value":63338.9,
"proID":"ISB"
},
{
"label":"May 18",
"value":24451,
"proID":"LI8"
},
{
"label":"May 18",
"value":2616.5,
"proID":"TR2"
}
];
var propertiesObject = { // my object
type: 'mscolumn2d',
renderAt: 'chart-container',
width: '1000',
height: '500',
dataFormat: 'json',
dataSource: {
chart: {
caption: "Kilos per Date Comparison"
},
categories: [
{
category: []
}
]
}
};
var propCount = Object.keys(data).length; // getting object length
var checkSameLabel = data[0].label; // for reference reference inside the loop
var firstIndex = {"label":data[0].label}; // im taking first index of object and add manually
propertiesObject.dataSource.categories[0].category[0] = firstIndex; // adding the first index to my object
var currentProject = data[0].proID, counterCurrentProject = 0;
for(let i = 0; i < propCount; i++) {
if(checkSameLabel !== data[i].label) { // check if current value of label is not equal then add new data to my object
const value = data[i].label;
var obj = {
"label": value
};
propertiesObject.dataSource.categories[0].category[i] = value; // adding new data
}
checkSameLabel = data[i].label; // for the next check
}
console.log(JSON.stringify(propertiesObject));
document.getElementById("result").innerHTML = JSON.stringify(propertiesObject);
<div id="result"></div>
I'm expecting the output to be like this inside "category"
{ "label": "May 14" },
{ "label": "May 15" },
{ "label": "May 16" },
{ "label": "May 17" }
I don't know if it's because of my loop or im doing something wrong.
Instead of assigning to indicies of the array, use push instead, else you'll have empty values:
// data which im extracting
var data = [{
"label": "May 14",
"value": 56714.4,
"proID": "ISB"
},
{
"label": "May 14",
"value": 15902.5,
"proID": "LI8"
},
{
"label": "May 14",
"value": 419.6,
"proID": "TR2"
},
{
"label": "May 15",
"value": 2754.8,
"proID": "DAC"
},
{
"label": "May 15",
"value": 50845.7,
"proID": "ISB"
},
{
"label": "May 15",
"value": 19760.3,
"proID": "LI8"
},
{
"label": "May 15",
"value": 1704.1,
"proID": "TR2"
},
{
"label": "May 16",
"value": 2145.6,
"proID": "DAC"
},
{
"label": "May 16",
"value": 55666.4,
"proID": "ISB"
},
{
"label": "May 16",
"value": 15044.4,
"proID": "LI8"
},
{
"label": "May 16",
"value": 2413.5,
"proID": "TR2"
},
{
"label": "May 17",
"value": 6564.4,
"proID": "DAC"
},
{
"label": "May 17",
"value": 71379,
"proID": "ISB"
},
{
"label": "May 17",
"value": 21774.2,
"proID": "LI8"
},
{
"label": "May 17",
"value": 2191.4,
"proID": "TR2"
},
{
"label": "May 18",
"value": 63338.9,
"proID": "ISB"
},
{
"label": "May 18",
"value": 24451,
"proID": "LI8"
},
{
"label": "May 18",
"value": 2616.5,
"proID": "TR2"
}
];
var propertiesObject = { // my object
type: 'mscolumn2d',
renderAt: 'chart-container',
width: '1000',
height: '500',
dataFormat: 'json',
dataSource: {
chart: {
caption: "Kilos per Date Comparison"
},
categories: [{
category: []
}]
}
};
var propCount = Object.keys(data).length; // getting object length
var checkSameLabel = data[0].label; // for reference reference inside the loop
var firstIndex = {
"label": data[0].label
}; // im taking first index of object and add manually
propertiesObject.dataSource.categories[0].category[0] = firstIndex; // adding the first index to my object
var currentProject = data[0].proID,
counterCurrentProject = 0;
for (let i = 0; i < propCount; i++) {
if (checkSameLabel !== data[i].label) { // check if current value of label is not equal then add new data to my object
const value = data[i].label;
var obj = {
"label": value
};
propertiesObject.dataSource.categories[0].category.push(obj);
}
checkSameLabel = data[i].label; // for the next check
}
console.log(propertiesObject);
<div id="result"></div>
You could also simplify things by using a Set to keep track of labels added so far and forEaching over the data:
// data which im extracting
var data = [{
"label": "May 14",
"value": 56714.4,
"proID": "ISB"
},
{
"label": "May 14",
"value": 15902.5,
"proID": "LI8"
},
{
"label": "May 14",
"value": 419.6,
"proID": "TR2"
},
{
"label": "May 15",
"value": 2754.8,
"proID": "DAC"
},
{
"label": "May 15",
"value": 50845.7,
"proID": "ISB"
},
{
"label": "May 15",
"value": 19760.3,
"proID": "LI8"
},
{
"label": "May 15",
"value": 1704.1,
"proID": "TR2"
},
{
"label": "May 16",
"value": 2145.6,
"proID": "DAC"
},
{
"label": "May 16",
"value": 55666.4,
"proID": "ISB"
},
{
"label": "May 16",
"value": 15044.4,
"proID": "LI8"
},
{
"label": "May 16",
"value": 2413.5,
"proID": "TR2"
},
{
"label": "May 17",
"value": 6564.4,
"proID": "DAC"
},
{
"label": "May 17",
"value": 71379,
"proID": "ISB"
},
{
"label": "May 17",
"value": 21774.2,
"proID": "LI8"
},
{
"label": "May 17",
"value": 2191.4,
"proID": "TR2"
},
{
"label": "May 18",
"value": 63338.9,
"proID": "ISB"
},
{
"label": "May 18",
"value": 24451,
"proID": "LI8"
},
{
"label": "May 18",
"value": 2616.5,
"proID": "TR2"
}
];
var propertiesObject = { // my object
type: 'mscolumn2d',
renderAt: 'chart-container',
width: '1000',
height: '500',
dataFormat: 'json',
dataSource: {
chart: {
caption: "Kilos per Date Comparison"
},
categories: [{
category: []
}]
}
};
const labelsAdded = new Set();
data.forEach(({ label }) => {
if (labelsAdded.has(label)) {
return;
}
labelsAdded.add(label);
propertiesObject.dataSource.categories[0].category.push({ label });
});
console.log(propertiesObject);
Or, by creating a Set of the label strings, and then using .map:
// data which im extracting
var data = [{
"label": "May 14",
"value": 56714.4,
"proID": "ISB"
},
{
"label": "May 14",
"value": 15902.5,
"proID": "LI8"
},
{
"label": "May 14",
"value": 419.6,
"proID": "TR2"
},
{
"label": "May 15",
"value": 2754.8,
"proID": "DAC"
},
{
"label": "May 15",
"value": 50845.7,
"proID": "ISB"
},
{
"label": "May 15",
"value": 19760.3,
"proID": "LI8"
},
{
"label": "May 15",
"value": 1704.1,
"proID": "TR2"
},
{
"label": "May 16",
"value": 2145.6,
"proID": "DAC"
},
{
"label": "May 16",
"value": 55666.4,
"proID": "ISB"
},
{
"label": "May 16",
"value": 15044.4,
"proID": "LI8"
},
{
"label": "May 16",
"value": 2413.5,
"proID": "TR2"
},
{
"label": "May 17",
"value": 6564.4,
"proID": "DAC"
},
{
"label": "May 17",
"value": 71379,
"proID": "ISB"
},
{
"label": "May 17",
"value": 21774.2,
"proID": "LI8"
},
{
"label": "May 17",
"value": 2191.4,
"proID": "TR2"
},
{
"label": "May 18",
"value": 63338.9,
"proID": "ISB"
},
{
"label": "May 18",
"value": 24451,
"proID": "LI8"
},
{
"label": "May 18",
"value": 2616.5,
"proID": "TR2"
}
];
var propertiesObject = { // my object
type: 'mscolumn2d',
renderAt: 'chart-container',
width: '1000',
height: '500',
dataFormat: 'json',
dataSource: {
chart: {
caption: "Kilos per Date Comparison"
},
categories: [{
category: [...new Set(data.map(({ label }) => label))].map(label => ({ label }))
}]
}
};
console.log(propertiesObject);
There are a few errors
You created variable 'obj', but not using it
var obj = {
"label": value
};
// No good
propertiesObject.dataSource.categories[0].category[i] = value;
// Should be this, but still not correct, see point (2)
propertiesObject.dataSource.categories[0].category[i] = obj;
You are adding elements to array by setting it with index, you should use array push instead
// No good
propertiesObject.dataSource.categories[0].category[i] = obj;
// Should be
propertiesObject.dataSource.categories[0].category.push(obj);
// data which im extracting
var data = [
{
"label":"May 14",
"value":56714.4,
"proID":"ISB"
},
{
"label":"May 14",
"value":15902.5,
"proID":"LI8"
},
{
"label":"May 14",
"value":419.6,
"proID":"TR2"
},
{
"label":"May 15",
"value":2754.8,
"proID":"DAC"
},
{
"label":"May 15",
"value":50845.7,
"proID":"ISB"
},
{
"label":"May 15",
"value":19760.3,
"proID":"LI8"
},
{
"label":"May 15",
"value":1704.1,
"proID":"TR2"
},
{
"label":"May 16",
"value":2145.6,
"proID":"DAC"
},
{
"label":"May 16",
"value":55666.4,
"proID":"ISB"
},
{
"label":"May 16",
"value":15044.4,
"proID":"LI8"
},
{
"label":"May 16",
"value":2413.5,
"proID":"TR2"
},
{
"label":"May 17",
"value":6564.4,
"proID":"DAC"
},
{
"label":"May 17",
"value":71379,
"proID":"ISB"
},
{
"label":"May 17",
"value":21774.2,
"proID":"LI8"
},
{
"label":"May 17",
"value":2191.4,
"proID":"TR2"
},
{
"label":"May 18",
"value":63338.9,
"proID":"ISB"
},
{
"label":"May 18",
"value":24451,
"proID":"LI8"
},
{
"label":"May 18",
"value":2616.5,
"proID":"TR2"
}
];
var propertiesObject = { // my object
type: 'mscolumn2d',
renderAt: 'chart-container',
width: '1000',
height: '500',
dataFormat: 'json',
dataSource: {
chart: {
caption: "Kilos per Date Comparison"
},
categories: [
{
category: []
}
]
}
};
var propCount = Object.keys(data).length; // getting object length
console.log(propCount)
var checkSameLabel = data[0].label; // for reference reference inside the loop
var firstIndex = {"label":data[0].label}; // im taking first index of object and add manually
propertiesObject.dataSource.categories[0].category[0] = firstIndex; // adding the first index to my object
var currentProject = data[0].proID, counterCurrentProject = 0;
for(let i = 0; i < propCount; i++) {
if(checkSameLabel != data[i].label) { // check if current value of label is not equal then add new data to my object
const value = data[i].label;
var obj = {
"label": value
};
// Use Array.push() to add new data
propertiesObject.dataSource.categories[0].category.push(obj);
}
checkSameLabel = data[i].label; // for the next check
}
console.log(JSON.stringify(propertiesObject));
document.getElementById("result").innerHTML = JSON.stringify(propertiesObject);
<div id="result"></div>

Duplicate calls to http in Angular on Subscribe

I'm new to angular and trying to implement a dashboard application. The dashboard contains 50+ different charts so I decided to capture all the data of these charts user one API call, the json file is as follows
{
"site": "bje",
"date": "2018-03-09T00:00:00",
"charts": [
{
"code": "INDK-01",
"dataset": [
{
"name": "Actual",
"data": [
{
"label": "05 Jan 2018",
"value": 351,
"date": "2018-01-05T00:00:00"
},
{
"label": "12 Jan 2018",
"value": 373,
"date": "2018-01-12T00:00:00"
},
{
"label": "19 Jan 2018",
"value": 353,
"date": "2018-01-19T00:00:00"
},
{
"label": "26 Jan 2018",
"value": 379,
"date": "2018-01-26T00:00:00"
},
{
"label": "02 Feb 2018",
"value": 356,
"date": "2018-02-02T00:00:00"
},
{
"label": "09 Feb 2018",
"value": 371,
"date": "2018-02-09T00:00:00"
},
{
"label": "16 Feb 2018",
"value": 371,
"date": "2018-02-16T00:00:00"
},
{
"label": "23 Feb 2018",
"value": 368,
"date": "2018-02-23T00:00:00"
},
{
"label": "02 Mar 2018",
"value": 369,
"date": "2018-03-02T00:00:00"
},
{
"label": "09 Mar 2018",
"value": 371,
"date": "2018-03-09T00:00:00"
}
]
},
{
"name": "Budget",
"data": [
{
"label": "05 Jan 2018",
"value": 0,
"date": "2018-01-05T00:00:00"
},
{
"label": "12 Jan 2018",
"value": 0,
"date": "2018-01-12T00:00:00"
},
{
"label": "19 Jan 2018",
"value": 0,
"date": "2018-01-19T00:00:00"
},
{
"label": "26 Jan 2018",
"value": 0,
"date": "2018-01-26T00:00:00"
},
{
"label": "02 Feb 2018",
"value": 0,
"date": "2018-02-02T00:00:00"
},
{
"label": "09 Feb 2018",
"value": 0,
"date": "2018-02-09T00:00:00"
},
{
"label": "16 Feb 2018",
"value": 0,
"date": "2018-02-16T00:00:00"
},
{
"label": "23 Feb 2018",
"value": 0,
"date": "2018-02-23T00:00:00"
},
{
"label": "02 Mar 2018",
"value": 0,
"date": "2018-03-02T00:00:00"
},
{
"label": "09 Mar 2018",
"value": 331.02,
"date": "2018-03-09T00:00:00"
}
]
},
{
"name": "Target",
"data": [
{
"label": "05 Jan 2018",
"value": 0,
"date": "2018-01-05T00:00:00"
},
{
"label": "12 Jan 2018",
"value": 0,
"date": "2018-01-12T00:00:00"
},
{
"label": "19 Jan 2018",
"value": 0,
"date": "2018-01-19T00:00:00"
},
{
"label": "26 Jan 2018",
"value": 0,
"date": "2018-01-26T00:00:00"
},
{
"label": "02 Feb 2018",
"value": 0,
"date": "2018-02-02T00:00:00"
},
{
"label": "09 Feb 2018",
"value": 0,
"date": "2018-02-09T00:00:00"
},
{
"label": "16 Feb 2018",
"value": 0,
"date": "2018-02-16T00:00:00"
},
{
"label": "23 Feb 2018",
"value": 0,
"date": "2018-02-23T00:00:00"
},
{
"label": "02 Mar 2018",
"value": 0,
"date": "2018-03-02T00:00:00"
},
{
"label": "09 Mar 2018",
"value": 331.02,
"date": "2018-03-09T00:00:00"
}
]
}
]
},..............etc
] }
The service .ts file contain a function that return the data as follows:
getDashboardData(): Observable<ProcessedData>{
return this._http.get<ProcessedData>(this.baseUrl)
.map(res => res);
}
As well I have created one re-usable component which accept an input of chart code (ex. "INDK-01" in above json sample) an in ngOnInit I have this code
ngOnInit() {
this._service.getDashboardData(this.selectedSite, this.selectedDate)
.subscribe(res => {
this.BudgetData = res.charts.find(x => x.code == this.chartId)
.dataset.find(x => x.name == 'Budget')
.data
.sort();
this.TargetData = res.charts.find(x => x.code == this.chartId)
.dataset.find(x => x.name == 'Target')
.data
.sort();
.
.
.
});
in dashboard home component I add multiple
the problem that it makes multiple calls to the API everytime I load dashboard page, is there any way to avoid that? like for example store the data in a global object and from each chart will filter to get the proper data.
You need to first shareReplay(1) your observable something like following to cache the data:
const sharedOb = this._service.getDashboardData(this.selectedSite, this.selectedDate).shareReplay(1)
sharedOb.subscribe(x=>{
// do your work here
})
Now you can subscribe to sharedOb as many as times you want, there will only be one server round-trip.
You could use ".share".
this._service.getDashboardData(this.selectedSite, this.selectedDate).subscribe(res =>
{
this.BudgetData = res.charts.find(x => x.code == this.chartId)
.dataset.find(x => x.name == 'Budget')
.data
.sort();
this.TargetData = res.charts.find(x => x.code == this.chartId)
.dataset.find(x => x.name == 'Target')
.data
.sort();
}).share();

Process JSON data for Google org chart

I have a JSON data that looks like this
{
"name": "k11",
"id": "GOLD1501131955983380",
"data": {
"rank": "Agent",
"email": "k11#gmail.com",
"registrationDate": "13 Jan 2015 11:55:15 GMT",
"contact": "123123"
},
"children": [{
"name": "k11a",
"id": "GOLD1501131956858350",
"data": {
"registrationDate": "Jan 13, 2015 7:56:15 PM",
"rank": "Agent",
"email": "k11a#gmail.com",
"contact": "123123213123"
},
"children": [{
"name": "k11a2",
"id": "GOLD1501131959324173",
"data": {
"registrationDate": "Jan 13, 2015 7:59:25 PM",
"rank": "Agent",
"email": "k11a2#gmail.com",
"contact": "123123123"
},
"children": []
}, {
"name": "k11a1",
"id": "GOLD1501131958998436",
"data": {
"registrationDate": "Jan 13, 2015 7:58:27 PM",
"rank": "Agent",
"email": "k11a1#gmail.com",
"contact": "123123123"
},
"children": []
}]
}]
}
}
What I need to is to process this data to be compatible with google org chart that should look like this
{
"cols": [{
"id": "GOLD1501131955983380",
"name": "k11",
"data": {
"registrationDate": "Jan 13, 2015 7:59:25 PM",
"rank": "Agent",
"email": "k11a2#gmail.com",
"contact": "123123123"
}
}, {
}]
"rows": [{
"c": [{
"v": "k11"
}]
}, {
"c": [{
"v": "k11a2"
}, {
"v": "k11a"
}]
}]
}
Somewhat like the structured require by google charts.
Kindly please help me

Is this JSON structure suitable for a stacked bar chart using d3.js?

I need to create a stacked bar chart plus line graph. I'm thinking d3.js is the tool for the job, but I'm having problems binding my data. Is the following JSON formatted in a way that will work for the stack method?
{
"response": {
"qtime": 11,
"params": {
"id": "jb8wp1rw41v",
"format": "json"
}
},
"series": {
"twitter": [{
"date": "2013-08-20",
"value": 3
}, {
"date": "2013-08-21",
"value": 1
}, {
"date": "2013-08-22",
"value": 4
}, {
"date": "2013-08-23",
"value": 1
}, {
"date": "2013-08-24",
"value": 5
}, {
"date": "2013-08-25",
"value": 9
}, {
"date": "2013-08-26",
"value": 2
}, {
"date": "2013-08-27",
"value": 6
}, {
"date": "2013-08-28",
"value": 5
}, {
"date": "2013-08-29",
"value": 3
}, {
"date": "2013-08-30",
"value": 5
}, {
"date": "2013-08-31",
"value": 8
}, {
"date": "2013-09-01",
"value": 9
}, {
"date": "2013-09-02",
"value": 7
}],
"facebook": [{
"date": "2013-08-20",
"value": 0
}, {
"date": "2013-08-21",
"value": 1
}, {
"date": "2013-08-22",
"value": 3
}, {
"date": "2013-08-23",
"value": 6
}, {
"date": "2013-08-24",
"value": 10
}, {
"date": "2013-08-25",
"value": 21
}, {
"date": "2013-08-26",
"value": 28
}, {
"date": "2013-08-27",
"value": 21
}, {
"date": "2013-08-28",
"value": 10
}, {
"date": "2013-08-29",
"value": 6
}, {
"date": "2013-08-30",
"value": 0
}, {
"date": "2013-08-31",
"value": 15
}, {
"date": "2013-09-01",
"value": 21
}, {
"date": "2013-09-02",
"value": 1
}],
"email": [{
"date": "2013-08-20",
"value": 0
}, {
"date": "2013-08-21",
"value": 1
}, {
"date": "2013-08-22",
"value": 1
}, {
"date": "2013-08-23",
"value": 2
}, {
"date": "2013-08-24",
"value": 3
}, {
"date": "2013-08-25",
"value": 5
}, {
"date": "2013-08-26",
"value": 8
}, {
"date": "2013-08-27",
"value": 13
}, {
"date": "2013-08-28",
"value": 5
}, {
"date": "2013-08-29",
"value": 8
}, {
"date": "2013-08-30",
"value": 1
}, {
"date": "2013-08-31",
"value": 1
}, {
"date": "2013-09-01",
"value": 2
}, {
"date": "2013-09-02",
"value": 13
}],
"amazon_rank": [{
"date": "2013-08-20",
"value": 1001
}, {
"date": "2013-08-21",
"value": 2312
}, {
"date": "2013-08-22",
"value": 2300
}, {
"date": "2013-08-23",
"value": 5179
}, {
"date": "2013-08-24",
"value": 5112
}, {
"date": "2013-08-25",
"value": 2305
}, {
"date": "2013-08-26",
"value": 1902
}, {
"date": "2013-08-27",
"value": 1221
}, {
"date": "2013-08-28",
"value": 1010
}, {
"date": "2013-08-29",
"value": 2588
}, {
"date": "2013-08-30",
"value": 4093
}, {
"date": "2013-08-31",
"value": 4432
}, {
"date": "2013-09-01",
"value": 5002
}, {
"date": "2013-09-02",
"value": 3902
}],
"pinterest": [{
"date": "2013-08-20",
"value": 17
}, {
"date": "2013-08-21",
"value": 23
}, {
"date": "2013-08-22",
"value": 11
}, {
"date": "2013-08-23",
"value": 13
}, {
"date": "2013-08-24",
"value": 19
}, {
"date": "2013-08-25",
"value": 5
}, {
"date": "2013-08-26",
"value": 17
}, {
"date": "2013-08-27",
"value": 11
}, {
"date": "2013-08-28",
"value": 2
}, {
"date": "2013-08-29",
"value": 3
}, {
"date": "2013-08-30",
"value": 5
}, {
"date": "2013-08-31",
"value": 7
}, {
"date": "2013-09-01",
"value": 19
}, {
"date": "2013-09-02",
"value": 0
}]
}
}
You'll need to wrangle the data a little bit to get in a format that d3 likes, but there are built in functions to do all the work for you:
var companies = d3.layout.stack()(d3.values(json.series))
will give you a data structure similar to causes in the stacked bar chart example.
Basically, d3.values is taking your object with several arrays and turning in into an array of arrays. d3.layout.stack takes that two dimensional array, re structures it a a little bit and adds convenience functions that make it much simpler create a stacked bar chart.
I would recommend you to not use JSON at all since it is not streamable. Indeed, charts are often representing a big amount of datas and it is recommended to load their content progressively with the help of the XHR progress event.
Since most of the charts are tabular datas, i assume CSV is the better format for that purpose. If you still want be able to manage trees like with JSON, take a look at VarStream https://github.com/nfroidure/VarStream.
Here is an example of loading charts with a streamable format versus with JSON : http://server.elitwork.com/experiments/chartstream/index.html
The badest is your connection, the more you see how usefull is XHR Streaming.

Categories

Resources