JS: Iterate through the key, value pairs of an Object - javascript

I'm working on a Django framework project where I create a variable in Python to be a dict like:
dict = {
('ABC', 'XYZ'): [
('a', 'A'),
('b', 'B'),
('c', 'C'),
....
]
}
and I am including this data into an HTML's data-attribute when I render the page. When I grab this data in JS is when it gets difficult for me because JS only recognizes tuples like arrays I believe. I need to loop through this object in JS to create my HTML code. Trying something like console.log(Object.entries(obj)) creates thousands of arrays.
In pseudo code, I'm trying to accomplish:
function init(section) {
var test1 = [...create HTML code....]
return new Promise(function (resolve, reject) {
$(section).append(test1)
resolve()
}
$(document).ready(function () {
var section = $("#PageFilter")
var filters = $(section).data("filters")
for (const [key, value] of Object.entries(filters)) {
init(section).then(function () {
for (let x = 0; x < value.length; x++) {
var test2 = [...create some more HTML code...]
$('find_test1').append(test2)
}
}
}
})
UPDATE
Here is a sample of the DOM element's data attribute I was storing
<div
class="ms-auto py-4"
id="PageFilter"
data-filters="{('Region', 'cardinal'): [('EAST', 'EAST'), ('WEST', 'WEST')], ('State', 'state'): [('AL', 'AL'), ('AR', 'AR'), ('GA', 'GA'), ('KY', 'KY'), ('MS', 'MS'), ('NC', 'NC'), ....], ('Instatllation Type', 'installation_type'): [('BUILDING', 'Building'), ('EXTERNAL SERVICE', 'External Service'), ...]}"
></div>

After some clarification, I realize HTML's data attributes were only storing text, and the string was not in the JSON format to be parsed.
I was able to obtain the object in JS by doing a couple of things:
I changed my python dict to the format
{'key': (tuple), 'value': [(tuple), (tuple)]}
...so that JS can distinguish the key, value pair in its object.
I made sure I was using json.dumps(my_python_dict) when I was rendering the page to capture it in JSON.

Related

Find a key in Dictionary and access its value containing a KeyValue pair of Strings

I've got a dictionary of <long, List<KeyValuePair<string,string>> which I'm trying to access in JavaScript.
var data = new Dictionary<long, List<KeyValuePair<string, string>>>();
e.g: data would have Key:100, Value: Name, John
In Javascript,
I need to get all KeyValuePair<string,string>in data and add it into mu.Mappings using the long key.
ViewModel.Degrees.forEach(function(mu) {
mu.Mappings = ViewModel.MappingListResults.Keys(mu.ID)
.find((value => ViewModel.MappingListResults[key] === mu.ID)); //doesn't work
});
Any ideas or suggestions?

Javascript - How to display SessionStorage obj in HTML

I have object data in sessionStorage and I want to display them as a list in HMTL via loop. How do I Achieve this?
SesionStorage.cart data stringified:
[{"itemName":"WS: FaceShield, 10pcs pack","itemPrice":0,"itemQuantity":"1"},{"itemName":"Faceshield, 1 pc","itemPrice":0,"itemQuantity":"1"}]
What I want to do now is display them on a list after parsing them as JSON Object again.
Say you have
<ul id="myUL"></ul>
Here's a suggestion how to do it in JavaScript by using Array.prototype.reduce into a Web API DocumentFragment that can be later ParentNode.append() -ed into an UL HTMLElement:
// Let's define our array
const arr = [
{"itemName":"WS: FaceShield, 10pcs pack","itemPrice":0,"itemQuantity":"1"},
{"itemName":"Faceshield, 1 pc","itemPrice":0,"itemQuantity":"1"}
];
// Store it into LS...
localStorage.arr = JSON.stringify(arr);
// Read it from LS
const LS_arr = JSON.parse(localStorage.arr);
// Create a helper for new elements...
const ELNew = (sel, attr) => Object.assign(document.createElement(sel), attr || {});
// Loop the array and create LI elements
const LIS = LS_arr.reduce((DF, item) => {
DF.append(ELNew('li', {
textContent: `Name: ${item.itemName} Price: ${item.itemPrice}`
}));
return DF;
}, new DocumentFragment());
// Once our DocumentFragment is populated - Append all at once!
document.querySelector("#myUL").append(LIS);

Passing in data from Mongodb to HTML table using javascript using Node.js framework

I'm quite new at using node.js. Right now I'm trying to pull data from MongoDB and display it in a table using Javascript + HTML. However, my table is populating with undefined in all the fields. I think something is definitely wrong with how I'm reading data through to the Javascript function b/c I am able to render the full results from the people.js file straight to the webpage. Thank you in advance!! Below is my code:
Code for my people.js file:
exports.getPeople = (req, res) => {
People.find((err, docs) => {
if (err) { return next(err); }
if (docs != null){
console.log(docs.length)
docs.forEach(function(docs, index) {
console.log(index + " key: " + docs.name)
});
res.render('people', { people: docs });
}
else{
res.render('people', { people: docs() });
}
});
};
My Javascript + HTML that's populating my webpage.
script(type='text/javascript', src='http://code.jquery.com/jquery-1.9.1.js', charset='UTF-8')
script.
$(document).ready(function(){
var obj= '$(people)'
var tbl = "<table>"
var content="";
for(i=0; i<obj.length;i++){
content +=
'<tr>+<td>' +obj[i]["name"]+
'</td><td>'+obj[i]["type"]+
'</td><td>'+obj[i]["min_hours"]+
'</td><td>'+obj[i]["max_hours"]+
'</td><td>'+obj[i]["email"]+
'</td><td>'+obj[i]["phone_number"]+
'</td><td>'+ '<input type="button" value = "Update" onClick="Javacsript:deleteRow(this)">' +
'</td><td>'+'<input type="button" value = "Delete" onClick="Javacsript:deleteRow(this)">';
'</td></tr>';
}
content += "</table>"
$('#myTableData').append(content);
});
As you mentioned, you can render the array results from the people.js file directly into the webpage. So, you don't have to read the data through a JavaScript function using jQuery. The template engine language is built on top of JavaScript and it supports plenty of methods and features to do what you're trying to achieve here. So, for example, you may use an iteration method like each..in to build your table (see docs - Iteration):
// ...
body
table(id="myTableData")
// for each person in the people array (from people.js) ...
each person in people
// build a new table row
tr
// insert table data
td #{person.name}
td #{person.type}
td #{person.min_hours}
td #{person.max_hours}
td #{person.email}
td #{person.phone_number}
// add the update and delete buttons
td
input(type="button" value = "Update" onclick=" ... ")
input(type="button" value = "Delete" onclick=" ... ")
// move to next person in the people array ...
The Problem
var obj = '$(people)' does not work as you may expect. You want obj to hold the people array from the people.js file so that you can loop over each object in the array, but this is not what's happening. obj is actually a string value of length 9, so the for loop evaluates 9 string values (not objects). This is why all of your fields are undefined.
To see what I mean, run this code snippet:
var obj = '$(people)';
for (var i = 0; i < obj.length; i++){
console.log(obj[i]);
console.log(obj[i]["name"]);
}
The reason $(people) does not evaluate to an object is mainly because the parent element, script. causes everything below it to evaluate to plain text. The . after the tag causes the template engine to render plain text (see docs: Block in a Tag).
If you wanted to assign people to obj in your inline script you may try it this way:
script
| var obj = #{people};
But this will cause an Unexpected identifier JavaScript error because of the _id field on each item in people. By default _id is an ObjectID hex value from MongoDb so you would have to either remove the _id field from the docs or add quotes to each doc._id so it evaluates to a string. This would all have to be done in person.js before you return the data.
To see what I mean about the Unexpected identifier error, run this code snippet:
// works
var obj = { _id: '583ab33cdaf857b543c76afe',
name: 'john'};
// Error: Unexpected identifier
var obj = { _id: 583ab33cdaf857b543c76afe,
name: 'john'};

Accessing a javascript object in D3.js

A javascript data object (JSON notation) has been created with the following content:
"[
{"range":"Shape","values":[{"idx":0,"val":"Random"},{"idx":1,"val":"Line"},{"idx":2,"val":"Square"},{"idx":3,"val":"Circle"},{"idx":4,"val":"Oval"},{"idx":5,"val":"Egg"}]},
{"range":"Color","values":[{"idx":0,"val":"Red"},{"idx":1,"val":"Blue"},{"idx":2,"val":"Yellow"},{"idx":3,"val":"Green"},{"idx":4,"val":"Cyan"}]}
]"
In a next step the index of an ordinal value has to be found in this object. The function should find the index of the value 'Blue' in the range 'Color'.
So the function should have the meta scripting form
f("Color")("Blue")=1
What is the most elegant form to create such a function in the context of D3 and javascript?
Depending on your use case, it might make sense to convert the data structure to a different structure more suitable for direct access. E.g. you could convert your structure to
var data = {
Shape: ['Random', 'Line', ...],
// ...
};
and access it with
data['Shape'].indexOf('Line') // or data.Shape.indexOf('Line')
Or go even one step further and convert to
var data = {
Shape: {
Random: 0,
Line: 1,
// ...
},
// ...
};
and access it with
data['Shape']['Line'] // or data.Shape.Line
What the best solution is depends on the actual use case.
Converting the structure dynamically is pretty straight forward. Here is an example to convert it to the first suggestion:
var newData = {};
data.forEach(function(item) {
newData[item.range] =
item.values.map(function(value) { return value.val; });
});
This would also reduce redundancy (e.g. idx seems to correspond with the element index).
Would this work for you ?
var dataJson = '[ \
{"range":"Shape","values":[{"idx":0,"val":"Random"},{"idx":1,"val":"Line"},{"idx":2,"val":"Square"},{"idx":3,"val":"Circle"},{"idx":4,"val":"Oval"},{"idx":5,"val":"Egg"}]},\
{"range":"Color","values":[{"idx":0,"val":"Red"},{"idx":1,"val":"Blue"},{"idx":2,"val":"Yellow"},{"idx":3,"val":"Green"},{"idx":4,"val":"Cyan"}]}\
]';
var data = JSON.parse(dataJson);
for (each in data){
if ( (data[each].range) === 'Color'){
for (eachVal in data[each].values){
if (data[each].values[eachVal].val === 'Blue'){
alert(data[each].values[eachVal].idx);
}
}
} ;
}
And here is the JSFiddle for you too.

Updating D3.js (NVD3.js) Data by Merge

I'm working on some realtime graphs built with NVD3.js. I currently refresh each chart with the following:
function reDraw(c) {
d3.json(c.qs, function(data) {
d3.select(c.svg)
.datum(data)
.transition().duration(500)
.call(c.chart);
});
}
c looks like:
function Chart(svg, qs, chart) {
this.qs = qs;
this.svg = svg;
this.ylabel;
this.chart;
}
This works fairly well, but with each refresh I am fetching the whole time series again. It would be more efficient to only grab recent elements and update each graph. There are examples of doing this by appending elements (This answer NVD3 line chart with realtime data and this tutorial for example) , but this isn't ideal for me since some recent elements might be updated that are not the most recent element.
So what I'm looking to do is grab say the most recent minute (by setting query string (.qs) to only get the most recent minute, then take that result and do the following:
Overwrite any existing elements that have the same x value for each series with the most recent data
Append and elements when there are new x values from the update in each series
Expire elements past a certain age
Update the NVD3.js script with the new data. Maybe still use datum with the new merged object?
Can anyone suggest an elegant way to perform the above Merge operation? The existing data object looks like the following:
> d3.select(perf.svg).data()[0]
[
Object
key: "TrAvg"
values: Array[181]
__proto__: Object
,
Object
key: "RedisDurationMsAvg"
values: Array[181]
__proto__: Object
,
Object
key: "SqlDurationMsAvg"
values: Array[181]
__proto__: Object
]
> d3.select(perf.svg).data()[0][0]['values'][0]
Object {x: 1373979220000, y: 22, series: 0}
> d3.select(perf.svg).data()[0][1]['values'][0]
Object {x: 1373979650000, y: 2, series: 1}
The object returned would look something like the following (Except will only be maybe 6 elements or so for each object):
> d3.json(perf.qs, function(data) { foo = data })
Object {header: function, mimeType: function, response: function, get: function, post: function…}
> foo
[
Object
,
Object
,
Object
]
> foo[0]
Object {key: "TrAvg", values: Array[181]}
> foo[0]['values'][0]
Object {x: 1373980220000, y: 49}
In this newer object the series value is missing - maybe that needs to get added or perhaps D3 can do it?
For the time being I used linq.js to perform this operation, and then use .datum() to bind a new dataset each time. The solution isn't very elegant but it does seem to function:
function reDraw2(c, partial) {
if (partial) {
qs = c.qs.replace(/minago=[0-9]+/, "minago=1")
} else {
qs = c.qs
}
d3.json(qs, function(new_data) {
chart = d3.select(c.svg)
if (c.ctype == "ts" && partial) {
thirtyminago = new Date().getTime() - (60*30*1000);
old_data = chart.data()[0]
var union = new Array();
for (var i = 0; i < old_data.length; i++) {
var existing = Enumerable.From(old_data[i]['values']);
var update = Enumerable.From(new_data[i]['values']);
oldfoo = existing
newfoo = update
var temp = {}
temp['key'] = old_data[i]['key']
temp['values'] = update.Union(existing, "$.x").Where("$.x >" + thirtyminago).OrderBy("$.x").Select().ToArray();
union[i] = temp
}
chart.datum(union)
} else {
chart.datum(new_data)
}
chart.call(c.chart)
});

Categories

Resources