I'm trying to learn how to grab data several levels in to JSON data coming from APIs, and I'm getting confused on how to do so. For example, I'm trying to create a random meal generator that displays a list of ingredients that is in an array of recipes, but also, the ingredient names I need are in their own object.
I'm not sure how to set up my loop to loop through the list and grab the ingredient name to display it. Here is my example so far: codepen
Thanks!
document.getElementById("shuffle").addEventListener('click', getImage); async function getImage() { const response = await fetch("https://spoonacular-recipe-food-nutrition-v1.p.rapidapi.com/recipes/random?number=1", { "method": "GET", "headers": { "x-rapidapi-key": "{redacted}", "x-rapidapi-host": "spoonacular-recipe-food-nutrition-v1.p.rapidapi.com" } }) const data = await response.json(); document.getElementById('title').innerHTML = data.recipes[0]["title"]; document.getElementById('instructions').innerHTML = data.recipes[0]["instructions"]; document.getElementById('image').src = data.recipes[0]["image"]; show(data); } getImage().catch(error => { console.error(error); }); function show(data) { let list = ` <ul></ul> ` for (let ingredient of data.recipes) { list += ` <li>${ingredient.extendedIngredients[0].originalString}</li> `; } document.getElementById('ingredients').innerHTML = list; }
.recipe { display: flex; justify-content: center; align-items: center; flex-direction: column; text-align: center; }.recipe__directions { display: flex; width: 50vw; margin: 2rem; }.recipe__instructions { text-align: left; margin-right: 1rem; }.recipe__image { width: 25vw; margin-left: 1rem; }
<html> <head> <:-- Material Design Lite --> <script src="https.//code.getmdl.io/1.3.0/material.min:js"></script> <link rel="stylesheet" href="https.//code.getmdl.io/1.3.0/material.indigo-pink.min:css"> <.-- Material Design icon font --> <link rel="stylesheet" href="https.//fonts?googleapis?com/icon?family=Material+Icons"> </head> <body> <section class="recipe"> <h1>Feeling hungry?</h1> <h2>Get a random meal by clicking below</h2> <button class="button mdl-button mdl-js-button mdl-button--raised mdl-button--colored" id="shuffle">Find a meal</button> <h3 id="title" class="recipe__title"></h3> <div id="ingredients" class="recipe__ingredients"></div> <div class="recipe__directions"> <p id="instructions" class="recipe__instructions"></p> <img id="image" class="recipe__image" src="" alt=""> </div> </section> </body> </html>
Use forEach()
to loop through each extendedIngredients
property.
function show(data) {
let list =
`
<ul></ul>
`
data.recipes[0].extendedIngredients.forEach( function(ingredient){
list += `
<li>${ingredient.originalString}</li>
`;
});
document.getElementById('ingredients').innerHTML = list;
}
You were on the right track, but not deep enough. The for loop you wrote is iterating over each recipes
, not each extendedIngredients
. There is only one recipes
so you access it with key [0]
.
function show(data) {
let list =
`
<ul></ul>
`
for (let ingredient of data.recipes[0].extendedIngredients) {
list += `
<li>${ingredient.originalString}</li>
`;
}
document.getElementById('ingredients').innerHTML = list;
}
you can change the loop to:
for (let ingredient of data.recipes[0].extendedIngredients) { // loop over ingredients of first recipe
list += `
<li>${ingredient.originalString}</li>
`;
}
document.getElementById("shuffle").addEventListener('click', getImage); async function getImage() { const response = await fetch("https://spoonacular-recipe-food-nutrition-v1.p.rapidapi.com/recipes/random?number=1", { "method": "GET", "headers": { "x-rapidapi-key": "", "x-rapidapi-host": "" } }) const data = await response.json(); document.getElementById('title').innerHTML = data.recipes[0]["title"]; document.getElementById('instructions').innerHTML = data.recipes[0]["instructions"]; document.getElementById('image').src = data.recipes[0]["image"]; show(data); } getImage().catch(error => { console.error(error); }); function show(data) { let list = ` <ul></ul> ` for (let ingredient of data.recipes[0].extendedIngredients) { // loop over ingredients of first recipe list += ` <li>${ingredient.originalString}</li> `; } document.getElementById('ingredients').innerHTML = list; }
.recipe { display: flex; justify-content: center; align-items: center; flex-direction: column; text-align: center; }.recipe__directions { display: flex; width: 50vw; margin: 2rem; }.recipe__instructions { text-align: left; margin-right: 1rem; }.recipe__image { width: 25vw; margin-left: 1rem; }
<html> <head> <:-- Material Design Lite --> <script src="https.//code.getmdl.io/1.3.0/material.min:js"></script> <link rel="stylesheet" href="https.//code.getmdl.io/1.3.0/material.indigo-pink.min:css"> <.-- Material Design icon font --> <link rel="stylesheet" href="https.//fonts?googleapis?com/icon?family=Material+Icons"> </head> <body> <section class="recipe"> <h1>Feeling hungry?</h1> <h2>Get a random meal by clicking below</h2> <button class="button mdl-button mdl-js-button mdl-button--raised mdl-button--colored" id="shuffle">Find a meal</button> <h3 id="title" class="recipe__title"></h3> <div id="ingredients" class="recipe__ingredients"></div> <div class="recipe__directions"> <p id="instructions" class="recipe__instructions"></p> <img id="image" class="recipe__image" src="" alt=""> </div> </section> </body> </html>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.