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

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);

Related

Convert JSON array and nested data to CSV

I have an array of JSON objects that I'm trying to convert to CSV where the end format would look something like this in excel:
url
id
type
http://www.example.com
F22
a11y-true
C30
a11y-unknown
RC30
a11y-true
http://www.example.com/something-else
F22
a11y-true
F23
a11y-true
U10
a11y-unknown
CR14
a11y-unknown
RH03
a11y-true
given data such as...
[
{
"url": "https://www.example.com/something",
"ids": [
{ "id": "F22", "type": "a11y-true" },
{ "id": "C30", "type": "a11y-unknown" }
]
},
{
"url": "https://www.example.com/something-else",
"ids": [
{ "id": "F23", "type": "a11y-true" },
{ "id": "U10", "type": "a11y-unknown" },
{ "id": "CR14", "type": "a11y-unknown" },
{ "id": "RH03", "type": "a11y-true" }
]
}
]
I tried converting the JSON using:
const items = data
const header = Object.keys(items[0])
const csv = [header.join(','),...items.map(row => header.map(fieldName => JSON.stringify(row[fieldName])).join(','))].join('\r\n')
console.log(csv)
but I end up with only the first level converted over:
"https://www.example.com/something",[{"id":"F22","type":"a11y-true"},{"id":"C30","type":"a11y-unknown"}]
"https://www.example.com/something-else",[{"id":"F23","type":"a11y-true"},{"id":"U10","type":"a11y-unknown"},{"id":"CR14","type":"a11y-unknown"},{"id":"RH03","type":"a11y-true"}]
How can I also get the nested arrays converted to CSV so that each {} is a single entry?
There are libraries for working with csv in js but you could just define header fields and then pick those field values when you loop over ids
const data = [{"url":"https://www.example.com/something","ids":[{"id":"F22","type":"a11y-true"},{"id":"C30","type":"a11y-unknown"}]},{"url":"https://www.example.com/something-else","ids":[{"id":"F23","type":"a11y-true"},{"id":"U10","type":"a11y-unknown"},{"id":"CR14","type":"a11y-unknown"},{"id":"RH03","type":"a11y-true"}]}]
const separator = ', '
const header = ["url", "id", 'type']
const body = data.reduce((r, { url, ids }) => {
ids.forEach((e, i) => {
const first = i === 0 ? url : ''
const other = header.slice(1).map(k => e[k]).join(separator)
r.push([first, other].join(separator))
})
return r
}, [])
const result = `${header.join(separator)}\n${body.join('\n')}`
console.log(result)

Show JSON data in table with selectbox

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);
}
}

If object value exists in array, add to existing object

I have a function component that generates a linear chart in react based on an array of objects.
The data I'm pulling from the API looks like this:
{
"_id": "604face09b305032586fe235",
"username": "Demo",
"description": "0",
"duration": 0,
"date": "2021-03-15T18:52:10.749Z",
"createdAt": "2021-03-15T18:52:16.684Z",
"updatedAt": "2021-03-15T18:52:16.684Z",
"__v": 0
}
My code to generate the chart data is:
// GET Exercises
useEffect(() => {
axios.get("http://localhost:5000/exercises")
.then((result) => {
setIsLoaded(true);
setItems(result.data);
console.log(result.data)
})
.catch((error) => {
setIsLoaded(true);
setError(error);
})
}, [])
// chartdata
useEffect(() => {
const chartArray = items.map((item) => {
const container = {};
container.label = item.username;
container.data = [[stripDate(item.date), item.duration]]
return container;
});
setXp(chartArray);
}, [items])
However, the API could return multiple objects with "username": "Demo", what I want is that if the username value already exists in my chart data I want to update that container.data array with another array.
Current outcome:
{
"label": "Demo",
"data": [[15, "2021-03-15"]]
},
{
"label": "Demo",
"data": [[45, "2021-03-17"]]
}
What I want to achieve:
{
"label": "Demo",
"data": [[15, "2021-03-15"], [45, "2021-03-17"]]
}
Any help or guidance is appreciated.
You need to group your data based on the username value using array#reduce in an object accumulator. For repeated username push new data in the array. Then get the values from this accumulator using Object.values().
useEffect(() => {
const chartArray = Object.values(items.reduce((r, o) => {
r[o.username] = r[o.username] || { label: o.username, data: []};
r[o.username].data.push([o.duration, stripDate(o.date)]);
return r;
},{}));
setXp(chartArray);
}, [items])

Loop through JSON array of objects and get the properties based on the matching IDs from objects

My target is if the id from digital_assets and products matches then get the value of URL fro digital_assets and ProductName from products object. I'm able to traverse through the object and get the values of digital_assets and products but need some help to compare these two objects based on IDs to get the value of URL and ProductName. Below is what I've done so far.
var data = [{
"digital_assets": [{
"id": "AA001",
"url": "https://via.placeholder.com/150"
},{
"id": "AA002",
"url": "https://via.placeholder.com/150"
}]
}, {
"products": [{
"id": ["BB001", "AA001"],
"ProductName": "PROD 485"
},{
"id": ["BB002", "AA002"],
"ProductName": "PROD 555"
}]
}
];
$.each(data, function () {
var data = this;
//console.log(data);
$.each(data.digital_assets, function () {
var dAssets = this,
id = dAssets['id'];
// console.log(id);
});
$.each(data.products, function () {
var proData = this,
prod_id = proData['id'];
// console.log(prod_id);
$.each(prod_id, function () {
var arr_id = this;
console.log(arr_id);
});
});
});
Do I need to create new arrays and push the values into the new arrays? Then concat() these array to one. ? Bit lost any help will be appreciated.
Here is one way you can do this via Array.reduce, Array.includes, Object.entries and Array.forEach:
var data = [{ "digital_assets": [{ "id": "AA001", "url": "https://via.placeholder.com/150" }, { "id": "AA002", "url": "https://via.placeholder.com/150" } ] }, { "products": [{ "id": ["BB001", "AA001"], "ProductName": "PROD 485" }, { "id": ["BB002", "AA002"], "ProductName": "PROD 555" } ] } ]
const result = data.reduce((r,c) => {
Object.entries(c).forEach(([k,v]) =>
k == 'digital_assets'
? v.forEach(({id, url}) => r[id] = ({ id, url }))
: v.forEach(x => Object.keys(r).forEach(k => x.id.includes(k)
? r[k].ProductName = x.ProductName
: null))
)
return r
}, {})
console.log(Object.values(result))
You can use Array.prototype.find, Array.prototype.includes and Array.prototype.map to achieve this very gracefully.
let data = [
{
"digital_assets": [
{
"id": "AA001",
"url": "https://via.placeholder.com/150"
},
{
"id": "AA002",
"url": "https://via.placeholder.com/150"
}
]
},
{
"products": [
{
"id": ["BB001", "AA001"],
"ProductName": "PROD 485"
},
{
"id": ["BB002","AA002"],
"ProductName": "PROD 555"
}
]
}
];
// Find the 'digital_assets' array
let assets = data.find(d => d['digital_assets'])['digital_assets'];
// Find the 'products' array
let products = data.find(d => d['products'])['products'];
// Return an array of composed asset objects
let details = assets.map(a => {
return {
id : a.id,
url : a.url
name : products.find(p => p.id.includes(a.id)).ProductName
};
});
console.log(details);
changed answer to fit your needs:
var data = [
{
"digital_assets": [
{
"id": "AA001",
"url": "https://via.placeholder.com/150"
},
{
"id": "AA002",
"url": "https://via.placeholder.com/150"
}
]
},
{
"products": [
{
"id": ["BB001", "AA001"],
"ProductName": "PROD 485"
},
{
"id": ["BB002","AA002"],
"ProductName": "PROD 555"
}
]
}
]
let matchingIds = [];
let data_assetsObject = data.find(element => {
return Object.keys(element).includes("digital_assets")
})
let productsObject = data.find(element => {
return Object.keys(element).includes("products")
})
data_assetsObject["digital_assets"].forEach(da => {
productsObject["products"].forEach(product => {
if (product.id.includes(da.id)){
matchingIds.push({
url: da.url,
productName: product.ProductName
})
}
})
})
console.log(matchingIds);
working fiddle: https://jsfiddle.net/z2ak1fvs/3/
Hope that helped. If you dont want to use a new array, you could also store the respective data within the element you are looping through.
Edit:
I think i know why i got downvoted. My example works by making data an object, not an array. changed the snippet to show this more clearly.
Why is data an array anyway? Is there any reason for this or can you just transform it to an object?
Edit nr2:
changed the code to meet the expectations, as i understood them according to your comments. it now uses your data structure and no matter whats in data, you can now search for the objects containing the digital_assets / products property.
cheers
https://jsfiddle.net/2b1zutvx/
using map.
var myobj = data[0].digital_assets.map(function(x) {
return {
id: x.id,
url: x.url,
ProductName: data[1].products.filter(f => f.id.indexOf(x.id) > -1).map(m => m.ProductName)
};
});

How i can get data from another object?

Plunker
I have two structures - ingredients and recipes
[{
"id":"1",
"name": "Cucumber"
},
..
]
and
[{
"id":"1",
"name": "Salad1",
"recipein":[1, 3, 5]
}, {
...
}
]
and i want to show names of ingredients in each salad by press a button.
I filtered object to get ID of object, then i try to get a array of ingredients
getSalad(param:number) {
this.saladId = this.recipe.filter(rec => {
return rec.id.includes(param);
})
this.getNameOfIngredients(this.saladId)
}
getNameOfIngredients(saladArray:any) {
var ingredientsId = saladArray.map(function(num) {
return num.recipein;
});
i getting array [1,2,4] now i want to show all names of ingredients from this.ingredients with this array of id's.
How can i do this?
Plunker
I made updates in your plunker. I think thats what are you looking for: Plunker
getSalad(param:number) {
this.saladId = this.recipe.filter(rec => +rec.id === param )[0];
if(!this.saladId){
this.currentSalad = "Salad not found";
return;
}
this.currentSalad = this.getNameOfIngredients(this.saladId)
}
getNameOfIngredients(saladArray:any) {
return this.ingredients.filter( ing => {
return saladArray.recipein.indexOf(+ing.id) !== -1;
});
let _ingredients = []
this.ingredients.foreach((ingr)=>{
if(this.ingreIDArry.indexof(ingr.id) > -1){
_ingredients.push(ingr.name)
}
})
return _ingredients
is this what you want?
if you can flatten the array, it would be very straightforward for us to do lookups.
Here is what you could do.
const salads = [{
"id": "1",
"name": "Salad1",
"recipein": [1, 3, 5]
}];
const ingredients = [{
"id": "1",
"name": "Cucumber"
},
{
"id": "2",
"name": "Cucumber2"
},
{
"id": "3",
"name": "Cucumber3"
},
{
"id": "4",
"name": "Cucumber4"
},
{
"id": "5",
"name": "Cucumber5"
}
];
const flattenIngredients = (() => {
const output = {};
ingredients.forEach((ingredient) => {
output[ingredient.id] = ingredient;
});
return output;
})();
const getSalad = (saladId) => {
const filteredSalad = salads.filter((salad) => {
return saladId == salad.id;
});
if (filteredSalad.length > 0) {
const salad = filteredSalad[0];
return salad.recipein.map((receip) => flattenIngredients[receip].name);
}
}
console.log(getSalad(1));

Categories

Resources