I am having issues with using the .map function in JavaScript to extract a nested array from an api response.
here is the JSON:
[
{
"id": 3787,
"title": "Dummy title!",
"start_time": "2020-04-25T16:54:00.000Z",
"created_at": "2020-04-25T17:22:13.315Z",
"updated_at": "2020-04-25T17:32:15.364Z",
"incident_updates": [
{
"id": 9905,
"body": "Dummy Paragraph test!",
Here is the code that I put together my script.js file:
fetch(url)
.then((response) => {
if (!response.ok) {
throw Error("ERROR");
}
return response.json();
})
.then((data) => {
console.log(data);
const html = data
.map((item) => {
console.log(item.incident_updates[0]);
return `<div class="card card-space">
<div class="card-body">
<h5 class="card-title">${item.title}</h5>
<h6 class="card-subtitle mb-2 text-muted">${item.start_time}</h6>
<p class="card-text">${item.incident_updates.body}</p> // issues with this
</div>
</div>`;
})
.join("");
for whatever reason everything else is working fine like item.title & item.start_time however item.incident_updates.body doesn't work at all and in my HTML file it says "Undefined".
How am I able to get render the data from incident_updates.body?
Thanks guys!
incident_updates is an array, so you will need an index first to get the right element. Try something like this where i is the index of the element you're after:
var i = 0;
item.incident_updates[i].body
Since item.incident_updates is an array you can use map for that
const html = data
.map((item) => {
console.log(item.incident_updates[0]);
return `<div class="card card-space">
<div class="card-body">
<h5 class="card-title">${item.title}</h5>
<h6 class="card-subtitle mb-2 text-muted">${item.start_time}</h6>
{item.incident_updates.map((data)={return(<p class="card-text">${data.body}</p>)})}
</div>
</div>`;
})
Related
I'm trying to figure out a way to move on to the next (i) if a null image src is found. Right now the loops stops when it hits a null img src. Here's the error:
"TypeError: Cannot read properties of null (reading 'href')"
I saw some suggestions to use an if statement with continue, but couldn't get it to work. Looked for a while on stackoverflow and other forums but couldn't find anything that resolved it. Thanks in advance for any suggestions.
fetch(`https://real-estate12.p.rapidapi.com/listings/sale?state=CA&city=San%20Francisco&page=1&sort=relevant&type=single-family%2Cmulti-family`, {
"method": "GET",
"headers": {
"x-rapidapi-host": "real-estate12.p.rapidapi.com",
"x-rapidapi-key": "removingAPIkeyforStackOverflow"
}
})
.then(function (response) {
return response.json();
})
.then(function (data) {
houseCardsEl.innerHTML = '';
for (let i = 0; i < 12; i++) {
if (data.properties[i].primary_photo.href === null) {
continue;
}
houseCardsEl.innerHTML +=
`<div id="column-${i}" class="column is-one-quarter">
<div class="card">
<div class="card-image">
<figure id="houseImage" class="image is-4by3">
<img src="${data.properties[i].primary_photo.href}" alt="House image ${i}">
</figure>
</div>
</div>
</div>`;
}
})
.catch(err => {
console.error(err);
});
I suggest your slice and test your data:
NOTE: this will skip house image 2 in the display - you can solve that with a separate counter
We TRY to show 12, but will show as many as there actually are <= 12
const data = { properties: [
{primary_photo:{ href: "photo1.jpg"}},
{primary_photo:{ href: "photo2.jpg"}},
{ "noprimary_photo":""},
{primary_photo:{ href: "photo3.jpg"}},
]};
const html = data.properties.slice(0,12).map(({primary_photo},i) => primary_photo ? `<div id="column-${i}" class="column is-one-quarter">
<div class="card">
<div class="card-image">
<figure id="houseImage" class="image is-4by3">
<img src="${data.properties[i].primary_photo.href}" alt="House image ${i}">
</figure>
</div>
</div>
</div>` : '').join("")
console.log(html)
Browser Console Error
Uncaught ReferenceError: getNewCars is not defined at HTMLDivElement.onclick
Code Explained
I'm building a car selector form. How it works is there's categories (known as seasons) that can be clicked on to bring up a list of specific cars that pertain to that category (season).
Html
<div class="chooseCar">
<div class="chooseCarTabs">
</div>
<div class="chooseCarWrapper">
<div id="chooseCarSelection">
</div>
</div>
</div>
<script src="/public/theme/scripts/car-selection.js"></script>
car-selection.js
alert('new car-selection js')
let cars;
let seasons = [
{
"name": "Seasonal Cars",
"path": "seasonal.json"
},
{
"name": "Modern Cars",
"path": "modern.json"
},
{
"name": "Classic Cars",
"path": "classic.json"
},
{
"name": "Flag Cars",
"path": "flags.json"
}
];
let seasonTab = "Seasonal Cars";
const chooseCarBody = document.getElementById('chooseCarSelection');
const seasonsTabs = document.getElementsByClassName('chooseCarTabs')[0];
function loadCars(){
chooseCarBody.innerHTML = '';
cars.forEach(car => {
chooseCarBody.innerHTML += `
<div class="singleCar">
<div class="singleCarInner">
<img src="/public/images/avatars/${car.filename}" alt="${car.name}">
</div>
</div>
`
})
}
//Ajax Request
async function setSeasons() {
seasonsTabs.innerHTML = ''
await seasons.forEach(season => {
seasonsTabs.innerHTML += `
<div ${seasonTab == season.name ? 'class="activeSeasonTab"' : ''} onclick="getNewCars('${season.name}', '${season.path}' )">
${season.name}
</div>
`
});
}
//Will be replaced with AJAX Request
async function getNewCars(seasonName, season = seasons[0].path){
cars = null;
await fetch(`/public/data/cars/${season}`)
.then(response => response.json())
.then(data => {
console.log(data)
seasonTab = seasonName;
cars = data; console.log(cars)
})
.catch(error => console.log(error));
await loadCars()
}
async function initData(){
await setSeasons();
await getNewCars(seasons[0].name);
}
initData();
Extra code explanation
let cars; and let seasons work as a state of sorts. When a seasons tab is clicked on an ajax request is sent to get fill the cars state with cars for the category which is then looped through and populated on the page.
My Problem
When I reload the page the cars and category (season) tabs appear on the page just fine including the getNewCars(). But when I go to click on:
<div
${seasonTab == season.name ? 'class="activeSeasonTab"' : ''}
onclick="getNewCars('${season.name}', '${season.path}' )"
>
${season.name}
</div>
I get this error:
Uncaught ReferenceError: getNewCars is not defined at HTMLDivElement.onclick
Note, inline scripts I don't seem to get this error:
<div class="chooseCar">
<div class="chooseCarTabs">
</div>
<div class="chooseCarWrapper">
<div id="chooseCarSelection">
</div>
</div>
</div>
<script> /* All scripts in here*/</script>
How do I fix this and what's going wrong with my code that when import from another js file this happens?
I need to be able to append every even object on the left side of a vertical line, and every odd object on the right side. I am not sure how I can achieve this.
Sample of the JSON, (This is just dummy data for now) (url)
[{
"Year": 2010,
"Title": "Cadillac",
"Description": "Escalade ESV"
},
{
"Year": 1998,
"Title": "Volvo",
"Description": "V70"
},
{
"Year": 1992,
"Title": "Toyota",
"Description": "Camry"
},
{
"Year": 2012,
"Title": "Ford",
"Description": "Explorer"
}]
Heres my code:
fetch(url)
.then(result => {
return result.json();
})
.then (data =>{
console.log(data);
data.forEach( (point) => {
const appendToHtml = `
<div class="container left">
<div class="content">
<h2>${point.Title}</h2>
<p>${point.Description}</p>
<p>${point.Year}</p>
</div>
</div>
<div class="container right">
<div class="content">
<h2>${point.Title}</h2>
<p>${point.Description}</p>
<p>${point.Year}</p>
</div>
</div>
`;
$(".timeline").append(appendToHtml);
});
})
The issue is it append on the left AND the right.
Click here for an image of the issue.
I need to alternate
for example
Cadillac on the left, Volva on the right etc...
I cant seem to figure out what to do..
Thanks in advance!
You can calculate the odd or even of car index and based on that apply class left and right.
data.forEach( (point, index) => {
const isOdd = index % 2;
const appendToHtml = `
<div class="container ${isOdd ? 'right' : 'left' }">
<div class="content">
<h2>${point.Title}</h2>
<p>${point.Description}</p>
<p>${point.Year}</p>
</div>
</div>`;
$(".timeline").append(appendToHtml);
});
Here you go with a solution
fetch(url)
.then(result => {
return result.json();
})
.then (data =>{
console.log(data);
data.forEach( (point, i) => {
const appendToHtml = `
<div class=`container ${i%2 === 0 ? "right" : "left" }`>
<div class="content">
<h2>${point.Title}</h2>
<p>${point.Description}</p>
<p>${point.Year}</p>
</div>
</div>
`;
$(".timeline").append(appendToHtml);
});
})
Use template literal for finding odd even using mod function
I'm making a simple GK app that shows user information about countries and makes use of restcountries API.
I make request a to "https://restcountries.eu/rest/v2/all" which returns data about all countries.
But how do I make a request for just certain countries like the first 10 or 15 countries from the API , display it on the webpage or once all the content is returned, display only first 10 or 15 countries, and once the user scrolls down more content from the API is loaded?
rest countries API link : https://restcountries.eu/#rest-countries
HTML CODE:
<div class="list-of-countries">
//Countries are displayed in this block
</div>
JS CODE:
function displayCountries(countries) {
countries.forEach((country) => {
console.log(country);
let countryCard = $(`<div class="card" style="width: 18rem;">
<img src="${country.flag}" class="card-img-top" alt="${country.name} Flag">
<div class="card-body">
<h5 class="card-title">${country.name} </h5>
<p class="card-text">Population : ${country.population}</p>
<p class="card-text">Region : ${country.region}</p>
<p class="card-text">Capital : ${country.capital}</p>
</div>
</div>`);
$(".list-of-countries").append(countryCard);
});
}
window.onload = fetch("https://restcountries.eu/rest/v2/all")
.then((response) => {
if (!response.ok) {
throw Error(response.statusText);
}
return response.json();
})
.then((response) => {
displayCountries(response);
})
.catch((err) => {
console.log(err);
});
how would I be able to iterate over this JSON api response to get the "body" object from "Incident_updates" array?
Here is the JSON:
[
{
"id": 3787,
"title": "Dummy title!",
"start_time": "2020-04-25T16:54:00.000Z",
"created_at": "2020-04-25T17:22:13.315Z",
"updated_at": "2020-04-25T17:32:15.364Z",
"incident_updates": [
{
"id": 9905,
"body": "Dummy Paragraph test!",
I have tried using .map and foreach in my script.js file but no matter what I try and do, nothing seems to work and I get a "undefined undefined" error in the console. I also need to get the incident_updates.body response from all arrays that were in the api response. doing something like incident_updates[0].body works however I also need the responses from incident_updates[1].body etc etc.
This is my script.js file
fetch(url)
.then((response) => {
if (!response.ok) {
throw Error("ERROR");
}
return response.json();
})
.then((data) => {
console.log(data);
const html = data
.map((item) => {
console.log(item.incident_updates[0]);
return `<div class="card card-space">
<div class="card-body">
<h5 class="card-title">${item.title}</h5>
<h6 class="card-subtitle mb-2 text-muted">${item.start_time}</h6>
<p class="card-text">${item.incident_updates.body}</p> // issues with this
</div>
</div>`;
})
.join("");
Thanks for your help!
The incident_updates is an array of object, you need to retrieve one of the items using item.incident_updates[0].body. If it has multiple elements, you should consider creating another loop and retrieve them.
Here's an example that how you can output all item:
fetch(url).then((response) => {
if (!response.ok) {
throw Error("ERROR");
}
return response.json();
}).then((data) => {
console.log(data);
const html = data
.map((item) => {
console.log(item.incident_updates[0]);
return `<div class="card card-space">
<div class="card-body">
<h5 class="card-title">${item.title}</h5>
<h6 class="card-subtitle mb-2 text-muted">${item.start_time}</h6>
${item.incident_updates.map(update => `
<p class="card-text">${update.body}</p>
`).join('')}
</div>
</div>`;
})
.join("");
});
Edit
If you only need the first one of the item.incident_updates, just try item.incident_updates[0].body
fetch(url).then((response) => {
if (!response.ok) {
throw Error("ERROR");
}
return response.json();
}).then((data) => {
console.log(data);
const html = data
.map((item) => {
console.log(item.incident_updates[0]);
return `<div class="card card-space">
<div class="card-body">
<h5 class="card-title">${item.title}</h5>
<h6 class="card-subtitle mb-2 text-muted">${item.start_time}</h6>
<p class="card-text">${item.incident_updates[0].body}</p>
</div>
</div>`;
})
.join("");
});
not exactly the same example, but in this example you will see the logic to do what you need, I use destructuring to get the data in the function params and to access the first value of the array, I use square bracket notation:
const data = [
{
id: 3787,
title: "Dummy title!",
start_time: "2020-04-25T16:54:00.000Z",
created_at: "2020-04-25T17:22:13.315Z",
updated_at: "2020-04-25T17:32:15.364Z",
incident_updates: [
{
id: 9905,
body: "Dummy Paragraph 05!",
},
{
id: 9906,
body: "Dummy Paragraph 06!",
},
{
id: 9907,
body: "Dummy Paragraph 07!",
},
],
},
];
const html = data.forEach(({ title, start_time, incident_updates }) => {
const template = `
<div class="card card-space">
<div class="card-body">
<h5 class="card-title">${title}</h5>
<h6 class="card-subtitle mb-2 text-muted">${start_time}</h6>
${incident_updates
.map((incident) => `<p class="card-text">${incident.body}</p> `)
.join(" ")}
</div>
</div>
`;
console.log(template);
});