Angular - How can i transform an Object into an Array - javascript

I'm working on a line chart of ChartJS library.
I have this object and I would like to transform it in an array, because I want to use its data on it.
Searching on the net I found that map it's the easiest way to do that but I can't actually use it on Object, but only on arrays. How can i convert it in an array or simply use the json data on the line chart? That's the json object i have right now.
{labels: Array(2), values: Array(2)}
labels: (2) ["sales-be", "sales-mw"]
values: (2) [48, 8]
i tried like this but it gives me errors:
var labels = this.errorsList.map(function (e) {
return e.labels;
});
var datas = this.errorsList.map(function (e) {
return e.values;
});
TypeError: this.errorsList.map is not a function

The properties are already arrays. So you could access them directly.
Try the following
export class AppComponent {
errorsList = {
labels: ["sales-be", "sales-mw"],
values: [48, 8]
};
ngOnInit() {
this.chartData = [{
data: this.errorsList.values,
label: 'Sales',
fill: false
}];
this.chartLabels = this.errorsList.labels;
this.chartColors = [{
backgroundColor: 'rgba(0, 0, 0, 0)',
borderColor: 'rgba(255, 15, 15, 1)'
}];
};
}
Template
<div id="chart-container">
<canvas #myCanvas id="canvas" baseChart [chartType]="chartType" [datasets]="chartData" [labels]="chartLabels" [colors]="chartColors" [options]="chartOptions"></canvas>
</div>
Working example: Stackblitz
Here the errorsList is defined with hard values only for illustration. You don't have to define it in your code.
Again this code is an example and it's only here to illustrate how to use the properties from your object, nothing more.

Related

Dynamically create dataset objects for multi-line graphing, using pre-defined dataset object arrays (JavaScript / Chart.js)

How would I modify this code to dynamically create dataset objects inside of the 'datasets' array for each y-value data array that already exists? This is executed in the same function block as the function adding data to the arrays (where both fall inside of export class AppComponent implements OnInit { ngOnInit() { } }), answered previously here: https://stackoverflow.com/a/56710201/5067233 (as to provide proper source code credit).
My current method is obviously hard-coded and not efficient nor dynamic.
My generic code:
one = [];
two = [];
three = [];
...code that adds data to the arrays
// The actual graph formatting
this.chart = new Chart('canvas', {
type: 'line',
data: {
labels: this.one,
datasets: [
{
data: this.two,
label: 'two',
yAxisID: 'two',
borderColor: '#3CBA9F',
fill: false,
},
{
data: this.three,
label: 'three',
yAxisID: 'three',
scaleOverride: true,
borderColor: '#51b7ed',
fill: false,
},
...n amount of datasets here
]
},
});
A multi-line chart will have three important object arrays that need to be created, assigned to:
chart.data.labels - for x-axis labeling (ex. an independent variable like time)
chart.data.datasets - for y-axis labeling (including multiple lines)
chart.options.scales.yAxes - for the properties of the line(s)
If you have a pre-existing set of data (in this particular case objectArray) that contains pre-existing data associated with particular line names, you can create a constant array that contains strings of the same names (in this case NAME_ARRAY), as well as temporary arrays for each dataset (name1 = []; name2 = []; etc...) acquired by iterating through a for loop.
This can be seen with:
// 'N' PRE-DEFINED CONSTANTS
// Names of the lines you are graphing
const NAME_ARRAY = [
'name1',
'name2',
'name3'
];
// Colors of lines in same order as aforementioned names
const HEX_ARRAY = [
'#3CBA9F',
'#51b7ed',
'#FF0000'
];
// GRAPHING LINE PROPERTIES SHARED BY 'N' LINES
// Doesn't require arguments so can utilize .map() effectively
const datasetLineArray = NAME_ARRAY.map((value,index,array) => {
return {
id: value,
display: false,
ticks: {
// INSERT YOUR PROPERTIES HERE (although none required)
// max: 1000,
// min: 100000,
// reverse: true,
// stepSize: 10000,
// suggestedMax: 500,
// etc...
},
};
});
// Utilizes two arguments so needs object creation upon call rather than pre-defined array mapping (as in .map())
function addDataToDataset(dataArray, index) {
const tempObject = {
data: dataArray,
label: NAME_ARRAY[index],
yAxisID: NAME_ARRAY[index],
borderColor: HEX_ARRAY[index],
fill: false,
scaleOverride: true,
};
return tempObject;
}
// CHART.JS GRAPH CREATION
export class AppComponent implements OnInit {
// Store dataset objects
Dataset_Object_Array = [];
// Store data with same name as incoming objects
name1 = [];
name2 = [];
name3 = [];
// Essentially main()
ngOnInit() {
for (const categoryArray in objectArray) {
const categoryObject = objectArray[categoryArray];
// these names are arbitrary, just note that categoryObject is an object that contains
// the property 'category' which is the equivalent of the name from the constant array
// 'NAME_ARRAY'; however, this object may contain data that we need to parse
// IMPORTANT BIT
this.Dataset_Object_Array.push(addDataToDataset(this[categoryObject.category], categoryArray));
}
// The actual graph formatting
this.chart = new Chart('canvas', {
type: 'line',
data: {
// **IMPORTANT BIT**
labels: this.one, // x-axis labeling
// **IMPORTANT BIT**
datasets: this.Dataset_Object_Array // multi-line y-axis labeling as well as data
},
options: {
responsive: true,
maintainAspectRatio: true,
legend: {
display: true
},
scales: {
xAxes: [{
display: true,
ticks: {
callback: function(value, index, values) {
return parseFloat(value).toFixed(3);
},
}
}],
// **IMPORTANT BIT**
yAxes: datasetLineArray, // property meta-data for the lines
}
}
});
}
}

How to assign a number of properties to an existing object IF that property also has nested properties inside of it?

My data contains an empty object which I would like to populate with properties. Currently it looks like this:
data: function() {
return {
chartData: {}
}
},
Essentially, I want to create this structure:
data: function() {
return {
chartData: {
labels: ["One", "Two"];
datasets: [{
data: ["5", "10"],
label: "Chart"
}]
}
}
}
This like of code successfully adds the labels property and value whilst keeping reactivity, however, I can't figure out how to also add the datasets property which has nested properties itself
this.chartData = Object.assign({}, this.chartData, { labels: ['One', 'Two']})
I figured this one out by reading https://v2.vuejs.org/v2/guide/reactivity.html , however, they haven't shown how to add properties which have nested properties.
Here's one method of building that object using the spread syntax:
// Empty chartData
const chartData = {};
// Your two sets of data
const labels = ['One', 'Two'];
const datasets = { datasets: [{ data: ['5', '10'], label: 'Chart'}] };
// Merge the existing chartData, and labels and datasets together
const newChartData = { chartData: { ...chartData, labels: [...labels], ...datasets } };
console.log(newChartData);

pie() does not accept an array of objects

I have the following code:
public data = [
{
value: 61,
color: 'orange',
},
{
value: 29,
color: 'white',
},
{
value: 10,
color: 'blue',
},
];
public pie = d3
.pie()
.padAngle(0)
.value((d: any) => d.value);
const arcs = this.pie(this.data);
Which is basically the outcome of some of the various tutorials about building a donut chart with d3js.
Now I would like to add a custom interface for the items in the data array and also properly type the d parameter in the .value() function.
The problem is, that the #types/d3 package defines the expected data array as number[] and the d parameter as number.
Which means that I cannot use a custom interface for the data items. The typings package for D3 seems to be wrong in this case because all the tutorials I've read do it this way and the code works just fine.
What are my options in this case? Are there any workarounds? Can I override the typings that get into my way?
d3's pie accepts a generic just for that.
Here's how to solve this:
interface IData {
value: number;
color: string;
}
const data: IData[] = [
{
value: 61,
color: 'orange',
},
{
value: 29,
color: 'white',
},
{
value: 10,
color: 'blue',
},
];
const pie = d3
.pie<IData>()
.padAngle(0)
.value(d => d.value);
const arcs = pie(data);

How to perform an histogram with the following dictionary?

I have a dictionary called dict that looks as follows:
var dict = {
'Ex': 6,
'C': 6,
'blue': 2,
'car': 2,
'yellow': 2,
'X': 4,
'X3': 2
};
I would like to plot an histogram of it, with the keys as the labels of the horizontal axis and the values of the dictionary that are the frecuency as the vertical axis, I tried:
<canvas id="myChart" width="100" height="100"></canvas>
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: [],
datasets: [{
label: '# Frecuencies Words',
data: [],
borderWidth: 1
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero:true
}
}]
}
}
});
However the problem is that I am not sure of how to proceed to use the values of the dictionary to perform the graph, I would like to appreciate any suggestion to achieve this, I built the following jsfiddle to explain better the situation: https://jsfiddle.net/xbbc677o/
You're not doing bad, all you need now is to map that object into the data and label fields. Let's begin with labels
Object.keys(dict) returns an array of all the keys from dict
So we put
labels: Object.keys(dict)
Now we need the values for the data array, with Object.keys and map we can do it easily, we use Object.keys to get an array of all the keys in dict and then map to get each value from it's key, like this:
data: Object.keys(dict).map(function (key) { return dict[key]; })
Working fiddle
Both Object.keys and map are part of the ECMAScript 5 specification, so this wont work on ES3 (IE 8 or lower), but you can get pollyfils for both of those functions:
Array.prototype.map polyfill
Object.keys polyfill

Plot the json array using jquery flot

var data =[ { label: "Foo", data: [ ["2012-09-01", 1], ["2012-10-01", -14], ["2012-11-01", 5] ] },
{ label: "Bar", data: [ ["2012-09-01", 13], ["2012-10-01", 11], ["2012-11-01", -7] ] }
];
var options = {
series: {
lines: { show: true },
points: { show: true }
}
};
<div id="placeholder"></div>
<script>
$.plot($('#placeholder'), data, options);
</script>
I am confused why the graph is not getting plotted with the data. Ignore my novice knowledge on flot. Can anyone give me an idea how i should be able to do it.
Are you sure flot can handle values formatted as strings? You should probably convert the strings to real dates or milliseconds...
You can use the moment.js library:
var data =[ { label: "Foo", data: [ [moment("2012-09-01","YYYY-MM-DD").toDate(), 1], ...
Flot does not automatically parse dates. If you want those to be used as-is then you should include the categories plugin. If you actually want to treat them as dates then you should convert them to dates as Nikos suggested and then take a look at the time plugin.

Categories