How do I fix the code in Javascript to avoid repetitive elements in HTML?

Viewed 61

index.html

 <!--FIRST PIZZA---FIRST CHUNK OF HTML CODE-->
        <div class="column-pizza-1">
          <a href="">
            <div class="pizza-item--img">
              <img src="" id="pizza-img-1" />
            </div>
            <div class="pizza-item--add" id="selected-1">Add</div>
          </a>
          <div class="pizza-item--price" id="pizza-price-1">Rs. --</div>
          <div class="pizza-item--name" id="pizza-name-1">--</div>
          <div class="pizza-item--desc" id="pizza-desc-1">--</div>
        </div>
<!--SECOND PIZZA---SECOND CHUNK OF HTML CODE-->
            <div class="column-pizza-2">
              <a href="">
                <div class="pizza-item--img">
                  <img src="" id="pizza-img-2" />
                </div>
                <div class="pizza-item--add" id="selected-2">Add</div>
              </a>
              <div class="pizza-item--price" id="pizza-price-2">Rs. --</div>
              <div class="pizza-item--name" id="pizza-name-2">--</div>
              <div class="pizza-item--desc" id="pizza-desc-2">--</div>
              <div class="pizza-item--sizes" id="pizza-size-2">
            </div>

pizzas.json

[
  {
    "id": 1,
    "name": "Tandoori Paneer",
    "img": "/images/pizza.png",
    "price": 200,
    "sizes": [0, 100, 200],
    "description": "Spiced paneer, Onion, Green Capsicum & Red Paprika in Tandoori Sauce",
    "cheese": [0, 100, 0]
  },
  {
    "id": 2,
    "name": "Veggie Supreme",
    "img": "images/pizza.png",
    "price": 250,
    "sizes": [0, 100, 200],
    "description": "Black Olives, Green Capsicum, Mushroom, Onion, Red Paprika, Sweet Corn",
    "cheese": [0, 100, 0]
  }
]

index.js

//FIRST PIZZA - loading json data and showing it on index.html page
fetch("pizzas.json").then((response) =>
  response.json().then((data) => {
    //console.log(data[0].name);
    document.querySelector("#pizza-img-1").src = data[0].img;
    document.querySelector("#pizza-name-1").innerHTML = data[0].name;
    document.querySelector(
      "#pizza-price-1"
    ).innerHTML = `Rs ${data[0].price.toFixed(2)}`;
    document.querySelector("#pizza-desc-1").innerHTML = data[0].description;
  })
);
//SECOND PIZZA
fetch("pizzas.json").then((response) =>
  response.json().then((data) => {
    //console.log(data[0].name);
    document.querySelector("#pizza-img-2").src = data[1].img;
    document.querySelector("#pizza-name-2").innerHTML = data[1].name;
    document.querySelector(
      "#pizza-price-2"
    ).innerHTML = `Rs ${data[1].price.toFixed(2)}`;
    document.querySelector("#pizza-desc-2").innerHTML = data[1].description;
  })
);

MY DOUBT:
As you can see in the above code, I want to display details of two pizza items whose details are stored in json file and I'm using vanilla javascript to load data from json to HTML. And for each each of the pizzas, I have created element in index.html which is not good. Let's suppose in future I want to display details of 50 pizzas, so that would mean creating 50 chunks of code in html.
Can someone please tell me how can I use only one chunk of the HTML code and use it multiple times to create as many pizza items using vanilla javascript.

MY TAKE ON:
I was thinking to store the json data as a global variable and then use onload() and ready() to load data but I'm not sure about how to do it.

2 Answers

You can create an HTML template in JavaScript and use it over to generate your multiple <div> based on data in JSON file.

Using Template Literals you can easily use with the loops

fetch("https://api.jsonbin.io/b/605b2c5aaee69516ee8a8866/2").then((response) =>
  response.json().then((data) => {

    let jsonSize = data.length;

    let htmlContent = '';
    for (let i = 0; i < jsonSize; i++) {
      let id = data[i].id;
      let name = data[i].name;
      let img = data[i].img;
      let price = data[i].price;
      let sizes = data[i].sizes;
      let description = data[i].description;
      let cheese = data[i].cheese;

      htmlContent += `
           <div class="column-pizza">
            <a href="">
              <div class="pizza-item--img">
                <img src="${img}" id="pizza-img-${i}" />
              </div>
              <div class="pizza-item--add" id="selected-${i}">Add</div>
            </a>
            <div class="pizza-item--price" id="pizza-price-${i}">₹${price}</div>
            <div class="pizza-item--name" id="pizza-name-${i}">${name}</div>
  <div class="pizza-item--desc" id="pizza-desc-${i}">${description}</div>
</div>`;
    }
    document.querySelector("#root").innerHTML = htmlContent;

  })
);
.column-pizza {
  height: auto;
  width: 50vv;
}


.pizza-item--add,
.pizza-item--price {
  border: none;
  color: white;
  padding: 15px 32px;
  text-align: center;
  text-decoration: none;
  display: inline-block;
  font-size: 16px;
}

.pizza-item--add {
  background-color: #4CAF50;
  /* Green */
}

.pizza-item--price {
  background-color: #333;
  /* Gray */
}
<div id="root"></div>

PS- Don't have pizza image placeholder, thus using some random and ️ images.

Here is a demo

  • you can use async/await to fetch json
  • use map to transform the array to tags
  • use innerHTML to append a bunch of html contents

document.addEventListener('DOMContentLoaded', async ev => {
  const res = await fetch('https://jsonplaceholder.typicode.com/photos')
  const data = await res.json()
  const photos = data.slice(0, 100)


  const appEl = document.querySelector('#app')
  appEl.innerHTML = photos.map((photo, index) => {
    return `<div class="photo" style="transition-delay: ${index / 10}s">
                  <div class="image">
                    <a href="${photo.url}"><img src="${photo.thumbnailUrl}" alt="thumbnailUrl" /></a>
                  </div>
                  <div class="title">
                    <a href="${photo.url}">${photo.title}</a>
                  </div>
                </div>`
  }).join('')
  setTimeout(() => {
    appEl.classList.add('loaded')
  }, 0)
}, false)
#app {
  display: flex;
  flex-flow: row wrap;
  justify-content: space-evenly;
  align-items: center;
  position: relative;
}

.photo {
  width: 200px;
  height: 200px;
  position: absolute;
  top: 0;
  left: 0;
  transform: translate(-100vw, -100vh);
}

#app.loaded .photo {
  position: static;
  transition: all ease 1s;
  transform: translate(0, 0);
}

.image {
  text-align: center;
  transition: transform ease 1s;
}

.image:hover {
  transform: scale(1.1);
}

.title a {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  width: 100%;
  display: inline-block;
  text-align: center;
  font-family: 'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif;
  color: midnightblue;
  text-decoration: none;
}

.title a:hover {
  color: dodgerblue;
}
<div id="app"></div>

Related