Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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>
like image 838
Mandela-EFX Avatar asked Jun 17 '26 04:06

Mandela-EFX


2 Answers

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>
like image 115
Jannes Carpentier Avatar answered Jun 19 '26 17:06

Jannes Carpentier


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>
like image 41
Cat Avatar answered Jun 19 '26 16:06

Cat



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!