Show JSON data in table with selectbox - javascript

I want to select every data with same key in json from selectbox. For example, I want to select all values ​​with "author" key by putting them in the selectbox.
In the same way, I want to select the values ​​corresponding to the "country" key by putting them in a selectbox.
My JSON
"kitap": [
{
"author": "Chinua Achebe",
"country": "Nigeria",
"imageLink": "images/things-fall-apart.jpg",
"language": "English",
"link": "https://en.wikipedia.org/wiki/Things_Fall_Apart\n",
"pages": 209,
"title": "Things Fall Apart",
"year": 1958
},
{
"author": "Hans Christian Andersen",
"country": "Denmark",
"imageLink": "images/fairy-tales.jpg",
"language": "Danish",
"link": "https://en.wikipedia.org/wiki/Fairy_Tales_Told_for_Children._First_Collection.\n",
"pages": 784,
"title": "Fairy tales",
"year": 1836
}
]
}
My javascript
let table2 = document.getElementById("tr2")
var books = fetch("kitap.json")
.then(res=> res.json())
.then(veri => {for(let data in veri ) {
for(deger of veri[data]) {
table2.innerHTML+= `
<td><select><option value="${deger.author}"></select></td>
<td><select><option value="${deger.country}"></select></td>
<td><select><option value="${deger.imageLink}"></select></td>
`
}
}})
how can i edit?

So this is one approach. The code is untested but should provide enough information for you to get started.
let table2 = document.getElementById("tr2");
let select1 = document.getElementById("ddlAuthor");
let select2 = document.getElementById("ddlCountry");
var books = fetch("kitap.json")
.then(res => res.json())
.then(veri => {
// Sets do not contain duplicates.
let setOfAuthors = new Set();
let setOfCountries = new Set();
for (let data in veri) {
for (deger of veri[data]) {
table2.innerHTML += `
<td><select><option value="${deger.author}"></select></td>
<td><select><option value="${deger.country}"></select></td>
<td><select><option value="${deger.imageLink}"></select></td>`
setOfAuthors.add(deger.author);
setOfCountries.add(deger.country);
}
// clear and fill <select> with <option>s.
PopulateDDL(select1, setOfAuthors);
PopulateDDL(select2, setOfCountries);
}
});
function populateDDL(ddl, setOfData) {
let distinctSortedArray = Array.from(setOfData).sort();
clearDDL(ddl);
for (var i = 0; i < distinctSortedArray.length; i++)
ddl.add(new Option(distinctSortedArray[i]));
}
function clearDDL(ddl) {
while (ddl.options.length) {
ddl.remove(0);
}
}

Related

How do I get into the array I got from json?

I have a JSON file. I'm pulling data from this file with fetch. But I want to get the first element in all the elements of the array I pulled. I tried this but couldn't find it. Can you help me ?
MY JSON DATA :
{
"cols": [
"Name Surname",
"Company",
"Email",
"Date",
"Country",
"City"
],
"data": [
[
"Hyacinth Vincent",
"Duis Corporation",
"iaculis.enim#magnaCrasconvallis.ca",
"28/06/2022",
"Eritrea",
"Lyubertsy"
],
[
"Brenden Martinez",
"Volutpat Nunc Associates",
"iaculis#estMauris.org",
"24/03/2021",
"British Indian Ocean Territory",
"Colwood"
],
[
"Lunea Kinney",
"Ornare Facilisis Eget Incorporated",
"rutrum.eu#liberoMorbiaccumsan.ca",
"20/10/2021",
"Jordan",
"Yorkton"
],
[
"Rhona Mooney",
"Sed Et PC",
"placerat#sodalesat.ca",
"10/11/2020",
"Azerbaijan",
"Shrewsbury"
]
]
}
MY JS CODE :
fetch("api/tesodev.json")
.then((response) => response.json())
.then((data) => {
let cols = data.cols;
let responseData = data.data;
for (let index = 0; index < responseData.length; index++) {
let newResponseData = responseData.map(function (el, i) {
console.log(el[i]);
});
}
console.log(cols[0]);
});
Exactly what I'm trying to do is to get to the first elements of all the elements of the data array.
I want to access the data of "Hyacinth Vincent", "Brenden Martinez", "Lunea Kinney", "Rhona Mooney".
The only thing you're doing wrong is mapping over the whole child array and logging every part of it, when what you want is the first element:
const data = {
"cols": [
"Name Surname",
"Company",
"Email",
"Date",
"Country",
"City"
],
"data": [
[
"Hyacinth Vincent",
"Duis Corporation",
"iaculis.enim#magnaCrasconvallis.ca",
"28/06/2022",
"Eritrea",
"Lyubertsy"
],
[
"Brenden Martinez",
"Volutpat Nunc Associates",
"iaculis#estMauris.org",
"24/03/2021",
"British Indian Ocean Territory",
"Colwood"
],
[
"Lunea Kinney",
"Ornare Facilisis Eget Incorporated",
"rutrum.eu#liberoMorbiaccumsan.ca",
"20/10/2021",
"Jordan",
"Yorkton"
],
[
"Rhona Mooney",
"Sed Et PC",
"placerat#sodalesat.ca",
"10/11/2020",
"Azerbaijan",
"Shrewsbury"
]
]
}
let cols = data.cols;
let responseData = data.data;
for (let index = 0; index < responseData.length; index++) {
console.log(responseData[index][0])
}
(I would strongly suggest you change your data format; an array of objects would be much less fragile:
...
"data": [
{
name: "Hyacinth Vincent",
company: "Duis Corporation",
email: "iaculis.enim#magnaCrasconvallis.ca",
date: "28/06/2022",
country: "Eritrea",
city: "Lyubertsy"
},
{
...
ummm...
I think there are multiple problems in this
newResponseData will be array of item having values undefined as console.log() returns undefined.
I think this two lines can help.
Can you check at your end
let responseData = data.data;
const finaldata = responseData.map(item => item [0])
You need to access the current row in your for loop, then access the first element of this row.
fetch("api/tesodev.json")
.then((response) => response.json())
.then((data) => {
let cols = data.cols;
let responseData = data.data;
for (let index = 0; index < responseData.length; index++) {
const myDataRow = responseData[index];
const theFirstDataOfMyRow = myDataRow[0];
console.log(theFirstDataOfMyRow);
}
console.log(cols[0]);
});
You can use a double index to access the first field. [i][0] will access the first field in the ith object,
let responseData = <json>;
for (let index = 0; index < responseData.length; index++) {
console.log(responseData[i][0]);
}
You're almost doing it the way you want it work.
const data = {
"cols": [
"Name Surname",
"Company",
"Email",
"Date",
"Country",
"City"
],
"data": [
[
"Hyacinth Vincent",
"Duis Corporation",
"iaculis.enim#magnaCrasconvallis.ca",
"28/06/2022",
"Eritrea",
"Lyubertsy"
],
[
"Brenden Martinez",
"Volutpat Nunc Associates",
"iaculis#estMauris.org",
"24/03/2021",
"British Indian Ocean Territory",
"Colwood"
],
[
"Lunea Kinney",
"Ornare Facilisis Eget Incorporated",
"rutrum.eu#liberoMorbiaccumsan.ca",
"20/10/2021",
"Jordan",
"Yorkton"
],
[
"Rhona Mooney",
"Sed Et PC",
"placerat#sodalesat.ca",
"10/11/2020",
"Azerbaijan",
"Shrewsbury"
]
]
}
// Simplyfied, get data, use only data, only putput first entry in the array.
data.data.forEach((person) => {
console.log(person[0])
})
// Would be something like this:
/*
fetch("api/tesodev.json")
.then((response) => response.json())
.then((data) => {
let cols = data.cols
let persons = data.data
for (i = 0; i < persons.length; i++) {
console.log(persons[i][0])
}
})
*/

How parse JSON with complex nesting and unnamed array?

I am trying to figure out how to parse the JSON response I receive when I make a call to a specific database (JSON response shown below) using vanilla javascript - and so far I have not had any luck. I am placing an API call to the Quickbase database and they have a standard formatting for their JSON response. The API i am calling can be found at this link: https://developer.quickbase.com/operation/runQuery.
Here is what a response from the API call looks like
{
"data": [
{
"6": {
"value": 11.0
},
"69": {
"value": "A"
},
"70": {
"value": "B"
}
},
{
"6": {
"value": 11.0
},
"69": {
"value": "C"
},
"70": {
"value": "D"
}
}
],
"fields": [
{
"id": 6,
"label": "Related Invoice",
"type": "numeric"
},
{
"id": 69,
"label": "TEST1",
"type": "text"
},
{
"id": 70,
"label": "TEST2",
"type": "text"
}
],
"metadata": {
"numFields": 3,
"numRecords": 2,
"skip": 0,
"totalRecords": 2
}
}
And this is what I want to parse it into (do NOT need to omit the JSON not shown here - I just did that for clarity)
{
"data": [
{
"Related Invoice":11.0,
"TEST1":"A",
"TEST2":"B"
},
{
"Related Invoice":11.0,
"TEST1":"C",
"TEST2":"D"
}
]
}
Below is the full javascript code i am using
let headers = {
'QB-Realm-Hostname': 'XXXXXX',
'User-Agent': 'Invoice',
'Authorization': 'XXXXXX',
'Content-Type': 'application/json'
}
let body =
{
"from": "bq2paydp2",
"select": [
6,
69,
70
],
"where": "{6.EX.11}",
"sortBy": [
{
"fieldId": 6,
"order": "ASC"
},
{
"fieldId": 69,
"order": "ASC"
}
]
}
const xmlHttp = new XMLHttpRequest();
xmlHttp.open('POST', 'https://api.quickbase.com/v1/records/query', true);
for (const key in headers) {
xmlHttp.setRequestHeader(key, headers[key]);
}
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState === XMLHttpRequest.DONE) {
console.log(xmlHttp.responseText);
let line_items = JSON.parse(this.responseText, dataReviver);
console.log(line_items);
//function dataReviver (key, value) {
//if (key = 6)
// {
// var newHeaderName = 99;
// return newHeaderName;
// }
//
// return value;
//}
//document.getElementById('abc').innerHTML = line_items.data[0][6].value;
function generateTableHead(table,tableData) {
let thead = table.createTHead();
let row = thead.insertRow();
for (let key of tableData) {
let th = document.createElement("th");
let text = document.createTextNode(key);
th.appendChild(text);
row.appendChild(th);
}
};
function generateTable(table, tableData) {
for (let element of tableData) {
let row = table.insertRow();
for (key in element) {
let cell = row.insertCell();
let text = document.createTextNode(element[key]);
cell.appendChild(text);
}
}
};
let table = document.querySelector("table");
let tableData = Object.keys(line_items.data[0]);
generateTableHead(table, tableData);
generateTable(table, line_items.data);
}
};
xmlHttp.send(JSON.stringify(body));
This is what I am trying to achieve
|-----------------------------------------|
| Count | Related Invoice | TEST1 | TEST2 |
|-------|-----------------|-------|-------|
| 1 | 11.0 | A | B |
|-------|-----------------|-------|-------|
| 2 | 11.0 | C | D |
|-----------------------------------------|
I need to accomplish 3 things:
#1 Rename "6", "69 and "70" to the corresponding fields.label ( "Related Invoice", "TEST1" and "TEST2" ).
#2 Take the value of the objects nested under the objects shown above in #1 ( 11.0, "A", "B", ... ) and set them as the value of the objects shown in #1 above. This would, for example, make 6 (Related Invoice) the key and 11.0 the value.
#3 I ultimately want to display this in a table on a webpage. the html and css I can handle its the Javascript and JSON that I am not that great with.
If you need me to clarify anymore information please let me know.
To transform the data in the way you're looking, you'll need to loop over the data key in the object and create a new array based on the result of the loop.
A way to do this is with Array.prototype.map(). With this you can loop over each item in the array and return a new value.
In this map loop you are looping over each item in the data array. For each item you'll want to get the id and label from the fields array and use that array to create a new object. To create a new object within in a loop, you could use the Array.prototype.reduce() method.
So in this case you'll have a nested loop. The inner loop will loop over the fields array and uses the id to get the correct value from data array. It then returns an object with the label and the value set like you requested. The surrounding map method will then return a new array with objects. Tadaa, magic!
const response = {
"data": [{
"6": {
"value": 11.0
},
"69": {
"value": "A"
},
"70": {
"value": "B"
}
},
{
"6": {
"value": 11.0
},
"69": {
"value": "C"
},
"70": {
"value": "D"
}
}
],
"fields": [{
"id": 6,
"label": "Related Invoice",
"type": "numeric"
},
{
"id": 69,
"label": "TEST1",
"type": "text"
},
{
"id": 70,
"label": "TEST2",
"type": "text"
}
],
"metadata": {
"numFields": 3,
"numRecords": 2,
"skip": 0,
"totalRecords": 2
}
};
const transformResponseData = (response) => {
const { data, fields } = response;
// Return a new array with objects based on the values
// of the data and fields arrays.
const revivedData = data.map(entry =>
fields.reduce((object, { id, label }) => {
object[label] = entry[id].value;
return object;
}, {})
);
// Combine the original object with the new data key.
return {
...response,
data: revivedData
};
};
const createTable = ({ data, fields }) => {
const table = document.createElement('table');
const tHead = table.createTHead();
const tBody = table.createTBody();
const tHeadRow = tHead.insertRow();
// Create the counts cell manually.
const tHeadRowCountCell = document.createElement('th');
tHeadRowCountCell.textContent = 'Count';
tHeadRow.append(tHeadRowCountCell);
// Create a head for each label in the fields array.
for (const { label } of fields) {
const tHeadRowCell = document.createElement('th');
tHeadRowCell.textContent = label;
tHeadRow.append(tHeadRowCell);
}
// Output all the values of the new data array.
for (const [index, entry] of data.entries()) {
const tBodyRow = tBody.insertRow();
// Create a new array with the index and the
// values from the object.
const values = [
index + 1,
...Object.values(entry)
];
// Loop over the combined values array.
for (const [index, value] of values.entries()) {
const tBodyCell = tBodyRow.insertCell();
tBodyCell.textContent = index === 1 ?
value.toFixed(1) :
value;
}
}
return table;
};
const data = transformResponseData(response);
const table = createTable(data);
document.body.append(table);

Replace keys based on another array of objects

I have two array of objects, Based on one array I need to replace the key of another array. Tried to use Object.Keys() but could not achieve it. Kindly suggest
// **Input :**
let sim = {
"header": [{
"VKORG": "1000",
"VTWEG": "10"
},
{
"VKORG": "1000",
"VTWEG": "20"
}
]
}
// **Reference Array:**
let columns = [{
"FIELD": "VKORG",
"FIELD_DESC": "Sales Organization"
},
{
"FIELD": "VTWEG",
"FIELD_DESC": "Distribution Channel"
}
]
/// **Code I tried**
for (let i = 0; i < sim.header.length; i++) {
if (Object.keys(sim[i].header) === Object.keys(columns[i].header)) {
sim[i].header[columns[i].header.FIELD_DESC] = sim[i].header[Object.keys(sim[i].header)]
}
}
console.log(sim);
Expected Output:
output = {
"header": [{
"Sales Organization": "1000",
"Distribution Channel: "
10 "
},
{
"Sales Organization": "1000",
"Distribution Channel": "20"
}
]
}
Is not perfect but try this
let sim = {
"header": [
{
"VKORG": "1000",
"VTWEG": "10"
},
{
"VKORG": "1000",
"VTWEG": "20"
}
]
};
let columns = [
{
"FIELD": "VKORG",
"FIELD_DESC": "Sales Organization"
},
{
"FIELD": "VTWEG",
"FIELD_DESC": "Distribution Channel"
}
];
const filter = {};
for (let i = 0; i < columns.length; i++) {
filter[columns[i].FIELD] = columns[i].FIELD_DESC;
}
sim.header = sim.header.map(el => {
const keys = Object.keys(el);
const newObj = {}
for (const key of keys) {
newObj[filter[key]] = el[key];
}
return newObj;
});
console.log(sim);
Here is an approach using Map and array.map . We store the columns as key value pair in Map , then while traversing the sim.header , just get the value from the map for the particular key and update it .
let sim = {
"header": [{
"VKORG": "1000",
"VTWEG": "10"
},
{
"VKORG": "1000",
"VTWEG": "20"
}
]
}
let columns = [{
"FIELD": "VKORG",
"FIELD_DESC": "Sales Organization"
},
{
"FIELD": "VTWEG",
"FIELD_DESC": "Distribution Channel"
}
]
var map = new Map();
columns.forEach(obj => {
map.set(obj.FIELD, obj.FIELD_DESC);
})
sim.header = sim.header.map(obj => {
var tempObj = {};
Object.keys(obj).forEach(key => {
tempObj[map.get(key)] = obj[key]
})
return tempObj;
})
console.log(sim);

How to filter out objects if two keys are duplicate

const obj =
[
{
"id":"1",
"name":"a",
"email":"abc#gmail.com",
"expiryType":"premium"
},
{
"id":"2",
"name":"b",
"email":"abc#gmail.com",
"expiryType":"gold"
},
{
"id":"3",
"name":"b",
"email":"test#gmail.com",
"expiryType":"premium"
},
]
can somebody please help me how to filter out objects where email is same but i want to keep the one with expiry Type is premium ? How to achieve this using Javascript
Expected output would be
const obj =
[
{
"id":"1",
"name":"a",
"email":"abc#gmail.com",
"expiryType":"premium"
},
{
"id":"3",
"name":"b",
"email":"test#gmail.com",
"expiryType":"premium"
},
]
Assuming you want to keep the latest year's entry, you can keep a Map of the email addresses and years you've seen. See comments:
// The new list
const filtered = [];
// Known emails
const known = new Map();
// Loop through...
for (const entry of obj) {
// Get this email and expiry
const {email, expiryYear} = entry;
// Get the previous info if any
const previous = known.get(email);
if (previous) {
// If the previous one is older than this one,
// replace it with this one
if (previous.expiryYear < expiryYear) {
filtered[previous.index] = entry;
}
} else {
// Add this to the known list and the filtered array
known.set(email, {
index: filtered.length,
expiryYear
});
filtered.push(entry);
}
}
const obj = [
{
"id":"1",
"name":"a",
"email":"abc#gmail.com",
"expiryYear":"2020"
},
{
"id":"2",
"name":"a",
"email":"abc#gmail.com",
"expiryYear":"2019"
},
{
"id":"3",
"name":"b",
"email":"test#gmail.com",
"expiryYear":"2020"
},
];
// The new list
const filtered = [];
// Known emails
const known = new Map();
// Loop through...
for (const entry of obj) {
// Get this email and expiry
const {email, expiryYear} = entry;
// Get the previous info if any
const previous = known.get(email);
if (previous) {
// If the previous one is older than this one,
// replace it with this one
if (previous.expiryYear < expiryYear) {
filtered[previous.index] = entry;
}
} else {
// Add this to the known list and the filtered array
known.set(email, {
index: filtered.length,
expiryYear
});
filtered.push(entry);
}
}
console.log(filtered);
This has the advantage of not constantly re-scanning the new list for known entries.
You can filter out whole object based on unique key you want as below.
const obj =
[
{
"id": "1",
"name": "a",
"email": "abc#gmail.com",
"expiryType": "premium"
},
{
"id": "2",
"name": "b",
"email": "abc#gmail.com",
"expiryType": "gold"
},
{
"id": "3",
"name": "b",
"email": "test#gmail.com",
"expiryType": "premium"
}
]
function arrayUnique(arr, uniqueKey) {
const flagList = []
return arr.filter(function(item) {
if (flagList.findIndex(flagItem => flagItem[uniqueKey] === item[uniqueKey]) === -1) {
flagList.push(item)
return true
}
})
}
Method Calling....
let newObj = arrayUnique(obj,'email')
Output:
newObj = [
{
"id": "1",
"name": "a",
"email": "abc#gmail.com",
"expiryType": "premium"
},
{
"id": "3",
"name": "b",
"email": "test#gmail.com",
"expiryType": "premium"
}
]
Hope this helps.
You can do it simply with 2 loops. Maybe not the fastes but the simplest:
function deleteDouble(array, objectKey) {
for (var i = 0; i < array.length; i++) {
for (var j = 0; j < array.length; j++) {
if (i == j) {
continue;
}
if (array[i][objectKey] == array[j][objectKey]) {
array.splice(i, 1);
i = 0;
j = 0;
break;
}
}
}
return array;
}
deleteDouble(obj, "email");

(ES6) Data from JSON to HTML (div's)

I have this JSON File:
{
"clubs": [
{
"name": "Feyenoord Rotterdam",
"origin": "Zuid-Holland",
"championships": "15"
},
{
"name": "Sparta Rotterdam",
"origin": "Zuid-Holland",
"championships": "6"
},
{
"name": "AZ Alkmaar",
"origin": "Noord-Holland",
"championships": "2"
},
{
"name": "Willem II",
"origin": "Noord-Brabant",
"championships": "3"
},
{
"name": "PSV Eindhoven",
"origin": "Noord-Brabant",
"championships": "24"
}
]
}
I want to put the data (name, origin, championships) from every club in a separate div. I'm trying to do that with ES6.
This is my code right now:
{
const createDiv = clubs => {
const $div = document.createElement(`div`);
$div.classList.add(`club-info`);
document.querySelector(`.clubs`).appendChild($div);
const $club = document.createElement(`p`);
$club.classList.add(`.clubname`);
$club.textContent = `${clubs.name}`;
const $origin = document.createElement(`p`);
$origin.classList.add(`.origin`);
$origin.textContent = `${clubs.origin}`;
const $championships = document.createElement(`p`);
$championships.classList.add(`.championships`);
$championships.textContent = `${clubs.championships}`;
document.querySelector(`.club-info`).appendChild($club);
document.querySelector(`.club-info`).appendChild($origin);
document.querySelector(`.club-info`).appendChild($championships);
};
const makeDivs = clubs => {
clubs.forEach(club => {
createDiv(club);
});
};
const parse = clubs => {
makeDivs(clubs);
};
const init = () => {
const url = `./assets/data/data.json`;
fetch(url)
.then(r => r.json())
.then(json => parse(json.clubs));
};
init();
}
The problem now is that I have 5 different divs with the class "club-info", but that all the data goes to the first div as you can see in the picture.
image problem
When you do
document.querySelector(`.club-info`).appendChild($club);
document.querySelector(`.club-info`).appendChild($origin);
document.querySelector(`.club-info`).appendChild($championships);
, it looks up the first .club-info element each time. It doesn't know that you want to use the element also stored in $div.
Since $div contains your current .club-info element, you can use that variable instead:
$div.appendChild($club);
$div.appendChild($origin);
$div.appendChild($championships);

Categories

Resources