简体   繁体   中英

For Loop on array from dynamic API in JSON format within template literals

Trying to do all of this with as much vanilla Javascript as possible without needing React, Angular or anything else. I'm rendering the HTML contents through my JS file. How do I do a for loop within the template literals ( ` )? I cannot get a loop working and I need it for live data display. With the code you see on the JS file I manually put in a 0 index to get the first astronaut from the array and it works and displays fine.

This is my JS file.

const apiData ={
    url: 'http://api.open-notify.org/astros.json'
}

const {url} = apiData
const apiUrl = `${url}`

fetch(apiUrl)
    .then( (data) => data.json() )
    .then ( (astronauts) => createHtml(astronauts) )

const createHtml = (data) => {
    console.log(data)
    const html = `
    <div> 
        Total People In Space: ${data.number} <br>
        Names: ${data.people[0].name} <br>
        Craft: ${data.people[0].craft}
    </div>
    `
    const astronautDiv = document.querySelector('.astronaut')
    astronautDiv.innerHTML = html
}

Here is the latest contents from the API in its JSON format.

{"number": 3, "people": [{"craft": "ISS", "name": "Chris Cassidy"}, {"craft": "ISS", "name": "Anatoly Ivanishin"}, {"craft": "ISS", "name": "Ivan Vagner"}], "message": "success"}

Heres my HTML file.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Space</title>
    <link rel="stylesheet" href="static/css/styles.css">
    <script src="static/js/main.js"></script>
</head>
<body>
    <div class="astronaut"></div>
</body>
</html>

Using.map and.join, we can construct a string within the template literal

 const JSONDATA = {"number": 3, "people": [{"craft": "ISS", "name": "Chris Cassidy"}, {"craft": "ISS", "name": "Anatoly Ivanishin"}, {"craft": "ISS", "name": "Ivan Vagner"}], "message": "success"} const createHtml = (data) => { const html = ` <div> Total People In Space: ${data.number} <br> ${data.people.map(x => `<div>Name: ${x.name}, Craft: ${x.craft}</div>`).join("")} </div> ` const astronautDiv = document.querySelector('.astronaut') astronautDiv.innerHTML = html } createHtml(JSONDATA);
 <,DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width. initial-scale=1.0"> <title>Space</title> <link rel="stylesheet" href="static/css/styles.css"> <script src="static/js/main.js"></script> </head> <body> <div class="astronaut"></div> </body> </html>

If you set the innerHTML of an element, it will wipe out any previous innerHTML (such as other astronauts).

To add several elements inside your div, you can use the insertAdjacentHTML method , like:

 const astronautsDiv = document.querySelector('.astronaut'), myData = simulateFetchAndParse(); insertNewHtml(myData); function insertNewHtml(data){ // Inserts astronaut count const numberSpan = `<span>Total People In Space: ${data.number}</span>`; astronautsDiv.insertAdjacentHTML("beforeend", numberSpan); // Inserts individual astronaut information for(let person of data.people){ const personDiv = ` <div class="person"> <div>Name: ${person.name}</div> <div>Craft: ${person.craft}</div> </div> `; astronautsDiv.insertAdjacentHTML("beforeend", personDiv); } } function simulateFetchAndParse(){ const data = { number: 2, people: [ { name: "Tasha Yar", craft: "Enterprise" }, { name: "Buzz Lightyear", craft: "None" } ] }; return data; }
 .astronaut{ margin: 1em 0 0 1em; padding: 1em 0.5em 0 0.5em; border: 1px solid grey; }.person{ margin: 1em 0; }
 <div class="astronaut"></div>

Alternatively, you could use a series of createElement and .appendChild calls (which avoids the use of template literals where malformed HTML could fail at runtime).

The code would look more like this:

 const astronautsDiv = document.querySelector('.astronaut'), myData = simulateFetchAndParse(); insertNewHtml(myData); function insertNewHtml(data){ // Makes a span with some text, and appends it to our container const numberSpan = document.createElement("span"); numberSpan.textContent = `Total People In Space: ${data.number}`; astronautsDiv.appendChild(numberSpan); for(let person of data.people){ // Makes three new divs (`personDiv` will contain the other two) const personDiv = document.createElement("div"), nameDiv = document.createElement("div"), craftDiv = document.createElement("div"); // Sets some text and a class nameDiv.textContent = `Name: ${person.name}`; craftDiv.textContent = `Craft: ${person.craft}`; personDiv.classList.add("person"); // So the CSS can style this div // Adds the two divs to `personDiv`, and adds `personDiv` to our container personDiv.appendChild(nameDiv); personDiv.appendChild(craftDiv); astronautsDiv.appendChild(personDiv); } } function simulateFetchAndParse(){ const data = { number: 2, people: [ { name: "Tasha Yar", craft: "Enterprise" }, { name: "Buzz Lightyear", craft: "None" } ] }; return data; }
 .astronaut{ margin: 1em 0 0 1em; padding: 1em 0.5em 0 0.5em; border: 1px solid grey; }.person{ margin: 1em 0; }
 <div class="astronaut"></div>

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM