Listing Orders Refactor
📝 We continue in the same project folder throughout this section.
Why refactor?
As we write our code, and especially as our projects grow, we want to regularly refactor our code when possible.
Now our code works, and this what we want to be focusing on at first, but it is also important to regularly look over things and see if we can improve.
This lesson will involve refactoring the single function we have into smaller ones. When possible, it is a good idea to have smaller functions which focus on single tasks. This helps with readability and debugging. The way you approach this is up to you, and often personal preference, but often the closer we can get a function to doing a single task, the better.
The single order function
The first task is to move the creation of the orders into a new function. Leaving the createOrdersList() function to loop over all orders.
Create new function, this is passed an order:
function createSingleOrder(order) {}
function createOrdersList() {…
Then move all code from inside of loop into new function, except the last line:
function createSingleOrder(order) {
// 2. paste content inside of function
const orderWrapper = document.createElement('div');
orderWrapper.className = 'order_wrapper';
const orderNumberEl = document.createElement('h4');
const orderNumber = document.createTextNode(`Order: ${order.id}`);
orderNumberEl.appendChild(orderNumber);
orderWrapper.appendChild(orderNumberEl);
const pizzaList = document.createElement('ul');
order.pizzas.forEach(function (pizza) {
const orderQuantityEl = document.createElement('span');
const quantity = document.createTextNode(`${pizza.quantity} - `);
orderQuantityEl.appendChild(quantity);
const pizzaNameElement = document.createElement('span');
const pizzaName = document.createTextNode(pizza.name);
pizzaNameElement.appendChild(pizzaName);
const pizzaItem = document.createElement('li');
pizzaItem.append(orderQuantityEl, pizzaNameElement);
pizzaList.appendChild(pizzaItem);
});
orderWrapper.appendChild(pizzaList);
}
function createOrdersList() {
orders.forEach(function (order) {
// 1. cut out the contents inside the loop- leave this last line where we add to DOM:
document.querySelector('#orders').appendChild(orderWrapper);
});
}
createOrdersList();
Next, we call the new function, in place of where we cut out the code, passing in each single order:
function createOrdersList() {
orders.forEach(function (order) {
// call function:
createSingleOrder(order);
document.querySelector('#orders').appendChild(orderWrapper);
});
}
createOrdersList();
This is now just calling the function, we are not actually doing anything with it. What we need to do is return the order from the new function, and add it to the DOM. Add this return statement to the bottom of the createSingleOrder function:
function createSingleOrder(order) {
// ...
return orderWrapper;
}
Store the return value into a variable:
function createOrdersList() {
orders.forEach(function (order) {
// 1. create variable:
const singleOrder = createSingleOrder(order);
// 2. then add to the aside section:
document.querySelector('#orders').appendChild(singleOrder);
});
}
createOrdersList();
The orders should again now show in the sidebar.
Refactoring the list of pizzas
This new function is still quite long, and we can also reduce this. Again, this is personal preference. I am going to move over the pizza list creation to a new function, this could also be re-used in the future.
Create new function called createListOfPizzas:
function createListOfPizzas(pizzas) {}
function createSingleOrder(order) {
// ...
Inside the createSingleOrder function we create a ul, followed by a forEach section.
Cut and paste this into our new function:
function createListOfPizzas(pizzas) {
// cut and past from createSingleOrder function:
const pizzaList = document.createElement('ul');
order.pizzas.forEach(function (pizza) {
const orderQuantityEl = document.createElement('span');
const quantity = document.createTextNode(`${pizza.quantity} - `);
orderQuantityEl.appendChild(quantity);
const pizzaNameElement = document.createElement('span');
const pizzaName = document.createTextNode(pizza.name);
pizzaNameElement.appendChild(pizzaName);
const pizzaItem = document.createElement('li');
pizzaItem.append(orderQuantityEl, pizzaNameElement);
pizzaList.appendChild(pizzaItem);
});
}
Since this function is being passed the pizzas, we can access them directly:
function createListOfPizzas(pizzas) {
const pizzaList = document.createElement('ul');
// 1. directly access pizzas (remove order.):
pizzas.forEach(function (pizza) {
const orderQuantityEl = document.createElement('span');
const quantity = document.createTextNode(`${pizza.quantity} - `);
orderQuantityEl.appendChild(quantity);
const pizzaNameElement = document.createElement('span');
const pizzaName = document.createTextNode(pizza.name);
pizzaNameElement.appendChild(pizzaName);
const pizzaItem = document.createElement('li');
pizzaItem.append(orderQuantityEl, pizzaNameElement);
pizzaList.appendChild(pizzaItem);
});
// 2. return list from function
return pizzaList;
}
Finally, we can call this function in place of where we removed this code:
function createSingleOrder(order) {
const orderWrapper = document.createElement('div');
orderWrapper.className = 'order_wrapper';
const orderNumberEl = document.createElement('h4');
const orderNumber = document.createTextNode(`Order: ${order.id}`);
orderNumberEl.appendChild(orderNumber);
orderWrapper.appendChild(orderNumberEl);
// call function
const pizzaList = createListOfPizzas(order.pizzas);
// and we are still adding it to the wrapper since we use the
// same variable name here:
orderWrapper.appendChild(pizzaList);
return orderWrapper;
}
This should still work as before. Refactoring like this may not always be for you, and you can decide how far you want to go. Nothing is changing in terms of the way our project works. We still only see the orders, but now we have three clear functions each with a specific task.