I am trying to populate my HTML template with data from a JSON file I have created. However, I have two different arrays in that file, each of them containing multiple objects, and I do not know how to loop through them since I need to loop through them in separate functions.
The JS code I have provided below works if I were to have one big array in the JSON file ("product" being the array I am looping through), the problem is that I need to loop through the "glass" and the "wood" arrays separately (in different functions). Ideally, the JS snippet below would loop through the "wood" array.
I have only fetched from one big array before, so I don't really know how to approach this issue. I know this must be something super easy, but I am stuck and would appreciate any hints I can get! Thanks in advance.
JS file:
function init() {
if (window.location.href.includes("wood")) {
fetchJson();
}
}
function fetchJson() {
fetch("products.json")
.then((res) => res.json())
.then(getWoodGallery(product));
}
function getWoodGallery(product) {
product.forEach(showWoodGallery);
}
/*--- display wood products ---*/
function showWoodGallery(product) {
console.log(product);
const woodTemplate = document.querySelector("#woodGalleryTemplate").content;
const woodTemplateCopy = woodTemplate.cloneNode(true);
const woodList = document.querySelector("#woodList");
woodTemplateCopy.querySelector("h2.name").textContent =
"Name: " + `${product.wood}`;
woodTemplateCopy.querySelector("p.dimensions").textContent =
"Dimensions: " + `${product.dimensions}`;
woodTemplateCopy.querySelector("h3.price").textContent =
"Price: " + `${product.price}`;
woodTemplateCopy.querySelector(".btn").textContent = `Buy Now`;
woodList.appendChild(woodTemplateCopy);
}
JSON file:
{
"wood": [
{
"id": "1",
"image": "http://mauriciolondono.be/wp/wp-content/uploads/2020/01/animales_1.jpeg",
"name": "Butterfly",
"dimensions": "30 x 45cm",
"price": 40,
"btn": ""
},
{
"id": "19",
"image": "http://mauriciolondono.be/wp/wp-content/uploads/2020/01/symmetry_4.jpeg",
"name": "Escher deconstructed",
"dimensions": "30 x 45cm",
"price": 20,
"btn": ""
}
],
"glass": [
{
"id": "20",
"image": "http://mauriciolondono.be/wp/wp-content/uploads/2020/01/vidrio_17.jpeg",
"name": "Juntos pero no revueltos",
"dimensions": "30 x 45cm",
"price": 20,
"btn": ""
},
{
"id": "21",
"image": "http://mauriciolondono.be/wp/wp-content/uploads/2020/01/vidrio_11.jpeg",
"name": "White & green",
"dimensions": "30 x 45cm",
"price": 20,
"btn": ""
}
]
}
You just need to loop over the JSON objects keys and conditionally run the function you need to run for that particular key.
function parse(payload) {
Object.keys(payload).forEach((key) => {
switch(key) {
case 'wood':
handleWood(payload[key]);
break;
case 'glass':
handleGlass(payload[key]);
break;
// so on...
}
})
}
Here, Object.keys will give you an array of all the keys of the object. We then iterate over the returned array with forEach running the callback for each iteration. Inside the callback we are just matching the key and running the required function.
Related
What I want
I have 2 different Java-Script arrays/objects but with matching Ids. I want to merge them into a new object. So both the main object data and any matched elements from the secondary object are merged into a combined result.
What I tried
I tried using Object.assign() function but with no success.
Given Input
Example code, so I have 2 separate objects (main and lines):
let main = [
{
"Id": "1",
"Name": "Testing data"
}
]
let lines = [
{
"OtherId": "1",
"code": "AU-29830"
},
{
"OtherId": "1",
"code": "AU-29854-Single"
},
{
"OtherId": "1",
"code": "TV-BB21084623"
},
{
"OtherId": "2",
"code": "Don't Merge"
},
{
"OtherId": "3",
"code": "Don't Merge"
}
]
Expected Output
I want to merge those 2 arrays, so that the output should be a single array containing the merged main-object. This merged main-object should contain the original content of itself plus nested the filtered secondary array (only containing matching objects). The filtering was done using the id from the main array's object which has to match (the slightly deviating id) from each object of the secondary-array.
The resulting array should look like this:
let result = [
{
"Id": "1",
"Name": "Testing data",
"lines": [
{
"OtherId": "1",
"ProductCode": "AU-29830"
},
{
"OtherId": "1",
"ProductCode": "AU-29854-Single"
},
{
"OtherId": "1",
"ProductCode": "TV-BB21084623"
}
]
}
]
As your main is an array, I'm assuming you might end up with more than one main item in it. If so, here's one way to merge your line items onto each one:
const mergedMainItems =
main.map(mainItem=>({
...mainItem,
lines: lines.filter(line=>mainItem["Id"] === line["OtherId"])
}))
I think for this example this will work:
let result = [];
result.push({...main[0]}); //or even result.push(main[0])
result[0].lines = [];
for(let l in lines){
if(lines[l].code != "Don't Merge"){
result[0].lines.push({OtherId: lines[l].OtherId, ProductCode: lines[l].code})
}
}
I have two arrays of object, the first array (printers, around 80 elements) is made of the following type of objects:
[{
printerBrand: 'Mutoh',
printerModel: 'VJ 1204G',
headsBrand: 'Epson',
headType: '',
compatibilty: [
'EDX',
'DT8',
'DT8-Pro',
'ECH',
],
cartridges: [],
},
....
]
The second array (cardridges, around 500 elements) is made of the following type of objects:
[
{
"customData": {
"brand": {
"value": {
"type": "string",
"content": "ECH"
},
"key": "brand"
},
"printer": {
"value": {
"type": "string",
"content": "c4280"
},
"key": "printer"
}
},
"name": "DT8 XLXL",
"image": {
"id": "zLaDHrgbarhFSnXAK",
"url": "https://xxxxxxx.net/images/xxxxxx.jpg"
},
"brandId": "xxxxx",
"companyId": "xxxx",
"createdAt": "2018-03-26T14:39:47.326Z",
"updatedAt": "2018-04-09T14:31:38.169Z",
"points": 60,
"id": "dq2Zezwm4nHr8FhEN"
},
...
]
What I want to do first is to is to iterate through the first array and and then iterate for all the cardridge available: if a the value customData.brand.value of a cardridge is included inside the array 'compatibility' of a printer, then I have to add this cardridge object inside the cardridges array of this printer. I have tried but somehow the iteration doesn't take place correctly. This is what I tried:
printers.forEach((printerItem) => {
const printer = printerItem;
printer.compatibilty.forEach((compatibilityItem) => {
const compatibility = compatibilityItem;
cardridges.forEach((cartridge) => {
if (compatibility === cartridge.customData.brand.value.content) {
printer.cartridges.push(cartridge);
}
});
});
});
What am I doing wrong?
You're accessing the wrong property. It should be cartridge.customData.brandName.value.content, carefully note brandName.value rather than brand.value
Your issue is that you're accessing it by the wrong property - brand and not brandName.
Furthermore, if you're targeting everything but IE, you could simplify your nested for loops to utilize some fancy ES6 array methods.
printers.forEach((p) => {
p.cartridges.push(cartridges.filter((c) => {
const brandName = c.customData.brandName.value.content;
return p.compatibilty.includes(brandName);
}));
});
Am getting Data from server in below JSON format
{
"Data": [
{
"Id": "1",
"Number": 0,
"Modify": {
"Id": 0,
"Name": "a"
}
},
{
"Id": "2",
"Number": 1,
"Modify": {
"Id": 1,
"Name": "b"
}
}
]}
And am trying to create a new copy(Rename) of Modify inside the same object because my other data is expecting JSON with same format but different name for modify.
So i though i would foreach and create copy of the same which will form like below
{
"Data": [
{
"Id": "1",
"Number": 0,
"Modify": {
"Id": 0,
"Name": "a"
},"New": {
"Id": 0,
"Name": "a"
}
},
{
"Id": "2",
"Number": 1,
"Modify": {
"Id": 1,
"Name": "b"
},
"New": {
"Id": 1,
"Name": "b"
}
}
]}
Is there a better approach i can rename the object or should i create a copy. What is the better way to copy ?
Thanks
For loop is a fine way to do that.. data[i].Name = data[i].Modify;. Im fairly sure there isn't a "better" way than this in Javascript.
There's no other way than the one suggested by #MjrKusanagi, nevertheless I suggest another approach.
Make a function that takes your original object and replaces the selected key with the new name, returning a new object without changing the original one (immutability)
The function could take 3 arguments:
function modifyObject(object, oldKey, newKey) {...}
Inside the function you could use the Object.assign method to create a copy of the original object (a copy, not a reference):
var newObj = Object.assign({}, object);
After that, you can change the key name by creating a new one and don't forget to remove old key from the new object:
newObj.newKey = newObj.oldKey;
delete newObj.oldKey,
Finally you can return this new object and even use this function every time you need to do anything similar.
Using the delete is considered bad practice, but at least here you are not mutating your original source, so you can depend in its content over all your application's life cycle.
I know there's plenty of answers on this and most are suggesting looping thru the object, returning what you need, I'm not sure this is the best approach, in my case anyway.
What I have is array with entries referencing to another array people(with id and name) by person_id and projects(with id and name) by project_id.
What I need is to be able to access project and person with a particular id inside the loop on entries, so I can get their names. Doing what others have suggested I'd loop thru people and projects inside each irritation of entries, which seems like awful lot of looping.
So I thought I'd make something I called a "hashtable" from both people and projects on init, which means pretty much creating a new objects people_hashtable and projects_hashtable where key would be the id
so
[
{
"id": "8",
"name": "John Doe"
}
]
would became
{
"8": {
"name": "John Doe"
}
}
this way I'd have easy access to the name without looping all the time while still maintaining the old array with its original order(that's why I'm not outputting it this way directly from server, you can't quite order an object and I'm using both people and projects in a selectbox, which needs to be ordered by name).
Am I doing it right? Are there better way? Or should I forget this completely and stick with the search loop as suggested in other question?
I'm trying to be as efficient as possible on both server and client side.
You basically doubled all the objects just to avoid loop. So, unless you have some bad performance issues, I would avoid that.
In case you really, really need a kind of hashmap, I would prefer storing the array's index instead of another copy of the object:
// array
var arr = [
{
"id": "8",
"name": "John Doe"
}
];
// lookup table
var lookup = {
"8": 0
}
Of course doing that, means you can't modifying the array's without rebuild the hashmap.
Generate it's quite simple:
var lookup = arr.reduce(function(lookup, item, index) {
lookup[item.id] = index;
return lookup;
}, {});
You can also use that to generate the object you mentioned your question:
var lookup = arr.reduce(function(lookup, item) {
lookup[item.id] = {name: item.name};
return lookup;
}, {});
But as I said it's something I would avoid.
Following code may help you. JSFIDDLE
var arr = [
{
"id": "8",
"name": "John Doe"
}
];
var obj = {};
for(var i=0; i< arr.length; i++){
obj[arr[i].id] = {name: arr[i].name};
}
console.log(obj);
var articles= {
"item1":{
"id":"155",
"name":"First Item",
"value":-5199.6
},
"item2":{
"id":"255",
"name":"Second Item",
"value":-424.91
}
}
var ids = [];
for(var item in articles) {
ids.push(articles[item]['id']);
}
console.log(ids);
This lib https://github.com/paularmstrong/normalizr makes it pretty easy to do. Both normalization and denormalization.
It can turn this
{
"id": "123",
"author": {
"id": "1",
"name": "Paul"
},
"title": "My awesome blog post",
"comments": [
{
"id": "324",
"commenter": {
"id": "2",
"name": "Nicole"
}
}
]
}
into this
{
result: "123",
entities: {
"articles": {
"123": {
id: "123",
author: "1",
title: "My awesome blog post",
comments: [ "324" ]
}
},
"users": {
"1": { "id": "1", "name": "Paul" },
"2": { "id": "2", "name": "Nicole" }
},
"comments": {
"324": { id: "324", "commenter": "2" }
}
}
}
and the other way around.
I have some JSON data which is in the following format:
[
{
"id": 145,
"Name": "John",
"company_name": "A",
"email": "john#gmail.com",
"country": "USA"
},
{
"id": 500,
"Name": "Mike",
"company_name": "B",
"email": "mike#gmail.com",
"country": "London"
},
{
"id": 100,
"Name": "Sally",
"company_name": "C",
"email": "sally#gmail.com",
"country": "USA"
}
]
Now, suppose I ask the user to enter an id, say 100. Then I need to display all the details for this id.
I am supposed to do this as a part of a web application,where I have to invoke an display the fields of a particular id. This would have been easy if I had a hash like implementation and could display all parameters based on the key-id.
Can anybody tell me how this can be done using such kind of data?
Thanks!
You could use something like this:
(Assuming the you have a variable data with your Json Object).
function getid(id) {
var nobj;
data.forEach(function(obj) {
if(obj.id == id)
nobj = obj;
});
return nobj
}
var neededobj = getid(100);
console.log(neededobj.Name + "\n" + neededobj.email + "\netc...");
But to get the Object you have to loop through your complete array,
until it finds the right Object
see this Fiddle
I think you are looking for Associative Array,
the simplex one would be,
var associativeArray = [];
associativeArray["one"] = "First";
associativeArray["two"] = "Second";
associativeArray["three"] = "Third";
alert(associativeArray.one);
And obviusly you can add json object in value place