Functions, Objects, & Looping
Creating functions
This project will have various tasks such as listing products, deleting products, toggling the modal visibility, and fetching product data from the API. It is often useful to group tasks like this into a function
used to perform a particular task.
Add the following code to your script.js
file:
// script.js
function renderProducts() {}
function
: the function keyword is used to define a function.renderProducts()
: this is the function name, with the parentheses()
following. Additional information can be passed to the function inside these parentheses, these are called parameters.{}
: the code/task we want to run is added between the curly braces.
Move all of the current code inside of the functions curly braces. Your full code should be as follows:
function renderProducts() {
const productList = document.getElementById("product-list");
const card = document.createElement("article");
card.setAttribute("class", "product-card");
card.innerHTML = `<section class="product-image">
<img
src="images/t-shirt-blue.png"
alt="blue t-shirt with short sleeves"
class="product-image"
/>
</section>
<section class="product-details">
<h3>Stylish long-sleeve t-shirt in blue / medium</h3>
<p>A stylish long sleeve blue t-shirt, in size medium.</p>
<p class="price">$20.95</p>
</section>`;
productList.appendChild(card);
}
You will notice no product displaying in the browser. This is because functions need to be called/invoked using the function name and ()
, add this just after the function:
renderProducts();
Advantages of functions
This can be an advantage because we may not always want the code to run immediately. For example, later we will have a function to delete a product and we only want this to run when the delete button is clicked.
Functions can also be reused, we can write code once and invoke it multiple times. In addition, different arguments can be passed to a function to produce different results. Here is an example:
function fullName(firstName, lastName) {
console.log(`User: ${firstName} ${lastName}`);
}
fullName("Homer", "Simpson"); // User: Homer Simpson
fullName("Lisa", "Simpson"); // User: Lisa Simpson
The above example uses backticks as we used when creating a product. Variables can be inserted inside of ${}
to merge data into the text.
Functions can also be a good way to organize our code. Code is grouped into tasks, and a descriptive name can be used to identify the task of the code.
You can find more information on functions here.
The product object
The product code we have is a template that we will repeat for each product:
card.innerHTML = `
<section class="product-image">
<img
src="images/t-shirt-blue.png"
alt="blue t-shirt with short sleeves"
class="product-image"
/>
</section>
<section class="product-details">
<h3>Stylish long-sleeve t-shirt in blue / medium</h3>
<p>A stylish long sleeve blue t-shirt, in size medium.</p>
<p class="price">$20.95</p>
</section>
`
The title, description, price etc will soon be changed to include dynamic data. This product data will need to be stored so we can repeat this structure for multiple products, a JavaScript object is ideal for this. Here is a how two product objects could look:
const product1 = {
name: 'Stylish long-sleeve t-shirt in blue / medium',
description: 'A stylish long sleeve blue t-shirt, in size medium.',
price: 20.95
}
const product2 = {
name: 'Stylish long-sleeve t-shirt in red / large',
description: 'A stylish long sleeve red t-shirt, in size large.',
price: 21.95
}
console.log(product1.name); // Stylish long-sleeve t-shirt in blue / medium
console.log(product2.price); // 21.95
const product1 =
: The object is stored into a const.{}
: The contents of the object is contained within curly braces.name: 'Stylish...',
: Object properties are created using name/value pairs, separated by a comma.product2.price
: Data is accessed by the variable name, then using dot notation (.
), the property name.
Objects can be created for anything that has multiple properties. An example could be a person object with properties such as age, height, gender, and occupation.
Creating a products array
Using this product structure we can group multiple objects into a JavaScript array
. An array is created using []
:
// add to top of script.js file
let products = [];
Arrays can contain any data such as numbers, strings of text, or booleans (true
/ false
):
[1, 32, 78,5];
['hey', 'you'];
We will use it to store multiple product objects. Update the script.js
:
let products = [
{
name: "Stylish long-sleeve t-shirt in blue / medium",
description: "A stylish long sleeve blue t-shirt, in size medium.",
price: 20.95,
},
{
name: "Stylish long-sleeve t-shirt in red / large",
description: "A stylish long sleeve red t-shirt, in size large.",
price: 21.95,
},
];
Looping over products
In programming, loops are used to perform repetitive tasks. We have two products in the array, and we want to repeat the product HTML code for each, with the dynamic data inserted (title, description, and price). Since we have an array (products
), JavaScript has a built-in array method to loop over the values called forEach
:
function renderProducts() {
const productList = document.getElementById("product-list");
// add the following
products.forEach();
const card = document.createElement("article");
The forEach
method calls a function for each value in the array:
products.forEach(function (product) {
console.log(product);
});
For each loop, the code inside the function will be repeated. Notice how the function is passed the product
inside the parentheses. This value will be the first array item on the first loop, the second array item on the second loop, and so on. This will log the two product objects to the console.
Dynamic product data
Now we have access to the product data, update the renderProducts()
function. The
function renderProducts() {
const productList = document.getElementById("product-list");
products.forEach(function (product) {
const card = document.createElement("article");
card.setAttribute("class", "product-card");
card.innerHTML = `<section class="product-image">
<img
src="images/t-shirt-blue.png"
alt="blue t-shirt with short sleeves"
class="product-image"
/>
</section>
<section class="product-details">
<h3>Stylish long-sleeve t-shirt in blue / medium</h3>
<p>A stylish long sleeve blue t-shirt, in size medium.</p>
<p class="price">$20.95</p>
</section>`;
productList.appendChild(card);
});
}
The following has been updated:
- Remove the
console.log
. - Leave the
const productList =
line in place. - Cut all the rest of the product generating code from inside the function.
- Paste inside of the function contained in the loop.
The loop will now repeat the product twice in the browser. Notice how the products are duplicated, this is because the elements we create are the same, such as <h3>Stylish long-sleeve t-shirt in blue / medium</h3>
. This can be updated to use the product data from the array. All of the product code is between backticks, meaning we can insert variables using ${}
.
Update the product-details
section to include the product
data:
<section class="product-details">
<h3>${product.name}</h3>
<p>${product.description}</p>
<p class="price">$${product.price}</p>
</section>
The title, description, and price will now be different for each product. We will come back to the image later in this section. This may seem a lot of code for two products, but we now have a template in place that can be used for as many products as we have in the array.
Final project code
// script.js
let products = [
{
name: "Stylish long-sleeve t-shirt in blue / medium",
description: "A stylish long sleeve blue t-shirt, in size medium.",
price: 20.95,
},
{
name: "Stylish long-sleeve t-shirt in red / large",
description: "A stylish long sleeve red t-shirt, in size large.",
price: 21.95,
},
];
function renderProducts() {
const productList = document.getElementById("product-list");
products.forEach(function (product) {
const card = document.createElement("article");
card.setAttribute("class", "product-card");
card.innerHTML = `<section class="product-image">
<img
src="images/t-shirt-blue.png"
alt="blue t-shirt with short sleeves"
class="product-image"
/>
</section>
<section class="product-details">
<h3>${product.name}</h3>
<p>${product.description}</p>
<p class="price">$${product.price}</p>
</section>`;
productList.appendChild(card);
});
}
renderProducts();