0

Instead of manually entering information for every product, like in below html page, I would like to dynamically build divs (3 per row) for each one of my sets of data: pastryData, coffeeData.

And then have a link on each image that when user clicks it will redirect him to product page with that specific item description.

I have following products.html page:

<div class="container">
    <div id="pastries">
        <h3>Pastries</h3>
        <div class="card">
            <img src="images/croissant.png" alt="croisant" style="width:100%">
            <p class="calories">200 calories</p>
            <p class="name">Croissant</p>
        </div>                  
    </div>

    <div id="coffee">                   
       <h3>Coffee</h3>
    </div>
</div>
...
<script src="js/products.js" type="text/javascript"></script>   
</body>

Here is my products.js file:

    var pastryData = [
       { 
        itemID: "1", 
        itemName: "Croissant", 
        itemDesc: "Light, airy and shatteringly crisp, with a deeply caramelized buttery flavor, these croissants are a labor of love that's absolutely worth the time.", 
        calories: "200", 
        price: 1.99, 
        image: "../images/croissant.png"
        },
       { 
        itemID: "2", 
        itemName: "Cinnamon-Date Buns", 
        itemDesc: "These delicious cinnamon buns are infused with puréed dates", 
        calories: "300", 
        price: 2.14, 
        image: "../images/cinnamon-date-buns.jpg"
        },
       { 
        itemID: "3", 
        itemName: "Savory Fondue Babka", 
        itemDesc: "This cheesy loaf goodness has an amazing flavor of foundue.", 
        calories: "320", 
        price: 2.32, 
        image: "../images/fondue-babka.jpg"
        },
       { 
        itemID: "4", 
        itemName: "Quinoa-Banana Muffins", 
        itemDesc: "Quinoa had never tasted better than in this flavorful muffin.", 
        calories: "330", 
        price: 1.78, 
        image: "../images/Quinoa-Banana-Muffins.jpg"
        },
    ];

    var coffeeData = [
       { 
        itemID: "9", 
        itemName: "Cappuccino", 
        itemDesc: "Cappuccino", 
        calories: "150", 
        price: 2.89, 
        image: "../images/Cappuccino.jpg"}
        },
       { 
        itemID: "10", 
        itemName: "Latte", 
        itemDesc: "Latte", 
        calories: "100", 
        price: 2.33, 
        image: "../images/latte.jpg"}
        },
       { 
        itemID: "11", 
        itemName: "Caffe Americano", 
        itemDesc: "Caffe Americano", 
        calories: "250", 
        price: 1.50, 
        image: "../images/caffe-americano.jpg"}
        },
       { 
        itemID: "12", 
        itemName: "Regular Coffee", 
        itemDesc: "Regular Coffee", 
        calories: "0", 
        price: 0.99, 
        image: "../images/coffee.jpg"}
        },
    ];

    function buildData(data, idName) {
  for (var prop of data) {
        var imageElem = document.createElement("img");
        imageElem.setAttribute("src", prop.image);
        imageElem.setAttribute("width", "100%");        
        imageElem.setAttribute("alt", prop.itemName);

        var paramCalories = document.createElement("p");
        paramCalories.className = "calories"
        paramCalories.innerText = prop.calories + " calories";

        var paramName = document.createElement("p");
        paramName.className = "name"
        paramName.innerText = prop.itemName;

        var cell = document.createElement("div");
        cell.className = "card";
        cell.appendChild(imageElem);
        cell.appendChild(paramCalories);
        cell.appendChild(paramName);

        document.getElementById(idName).appendChild(cell);
  }
}

This is all I have so far, but I am not sure how to actually make this work.

products.css

.card {
  box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2);
  max-width: 300px;
  margin: auto;
  text-align: center;
  font-family: arial;
}

.calories {
  color: grey;
  font-size: 18px;
}

.card button {
  border: none;
  outline: 0;
  padding: 12px;
  color: white;
  background-color: #000;
  text-align: center;
  cursor: pointer;  
  font-size: 18px;
}

.card button:hover {
  opacity: 0.7;
}

.card .left {
    float: left;
}

.card .name {
  color: brown;
  font-size: 24px;
}
Angelina
  • 2,175
  • 10
  • 42
  • 82

2 Answers2

1

I'm not going to make the homework for you, but you need to look into string interpolation. ES6 has made this easy using template string literals, but I guess you will have to use ES5 for school (as your example code doesn't use ES6).
You can get some inspiration here: How can I do string interpolation in JavaScript?

In theory you will:

  • Create a function that takes interpolated values (your json values), and return a fully generated html string for a single json object. You can use simple string concatenation if you want to;
  • Loop through the array of javascript values and call the function for each item. Concatenate the returned html for each item into a list;
  • Perform a single write back to the DOM (like you did in your example, for example using innerHTML).
html_programmer
  • 18,126
  • 18
  • 85
  • 158
1

I will not provide the answer directly but will try to articulate the way you could do it yourself.

There are few things you need to understand before you go ahead. Each element is a dom node. Where you want to render what item is basically up to you. Let's say you have a ul element. How would you do it?

Document.querySelector on MDN

const brandsContainer = document.querySelector('#brands');

const brands = ['foo','bar'];

You have accessed it. Now what you need to do is dynamically create elements and push it back to the dom node.

How ?

You will need to take a loop through each element and append them.

Document.createElement on MDN

brands.forEach(brand => {
  const brandListItem = document.createElement('li')
  // now you will have to update to text of the element;
  brandListItem.innerHTML = brand;
  // push it to the node you had queried earlier
  brandsContainer.appendChild(brandListItem)
))

Node.appendChild on MDN

Tân
  • 1
  • 15
  • 56
  • 102
Ozan
  • 1,623
  • 3
  • 13
  • 25