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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With