Video Course

Build an Interactive JavaScript Food Menu: Lesson 12 of 14

Add to Cart and Show Items in Modal

Up Next

Remove from Cart

Autoplaying in 7 seconds!

Cancel

We have buttons to add the item into our cart. However, it doesn't actually do anything. First, we need to make sure when the button is clicked, that it is added to our central store. Add the following to setup_listeners.js.

function getParentWithKey(element) {
  let parent = element.parentElement;

  while (parent && !parent.dataset.key) {
    parent = parent.parentElement;
  }

  return parent;
}

$('.add-to-cart').on('click', e => {
  const parent = getParentWithKey(e.currentTarget);

  const key = parseInt(parent.dataset.key, 10);
  store.trigger('ITEM_ADDED', { item: key });
});

Here, we add a helper method that will get the parent of the current object that has a data-key attribute. This should be the article element that the button is inside of in our markup. Then it uses parseInt to make the key an integer since they are stored as strings. Lastly, it triggers an ITEM_ADDED event on the store and passes the key in as the item that is to be added to the cart. This is why we keep the items in our store as a map where the keys are the IDs of each item. It makes looking them up extremely easy and quick.

Now we need to make sure that our reducer updates our state correctly. Add the following case to our reducer in index.js.

case 'ITEM_ADDED':
  return Object.assign({}, state, {
    cart: (new Set(state.cart)).add(data.item),
  });

This simply creates a new Set object and passes it the current Set of carts. It then uses the add method on the Set object to add the new item's ID to the list of items in the cart. We are using a Set so that we don't have to check if the item is already in the cart. JavaScript handles it for us!

Now that the event can be triggered, we now need to make two different things happen. We need to make the item on the menu fade a bit and disable the button. We also need to add the item to the modal that shows our cart. Let's start with making the item fade. Add the following to menu.js.

store.on('ITEM_ADDED', ({ cart }) => {
  const cartArray = [...cart];
  const articles = cartArray.map(id => `article[data-key='${id}']`);
  const buttons = cartArray.map(id => `article[data-key='${id}'] button.add-to-cart`);

  $(articles.join(', ')).addClass('in-cart');
  $(buttons.join(', ')).attr('disabled', 'disabled');
});

We are sttaching a callback to the ITEM_ADDED event on the store. We are using object destructuring in the parameters of our function to automatically pull out the cart for us. This is a shortcut instead of doing something like this instead: state.cart. Then we loop through all the IDs in the cart and add strings of their CSS selector into two array we created. Then we use the addClass helper we created to add a class to each article that will fade them out. We also grab all the buttons and add a disabled attribute to each of them. However, we are using a method we haven't created yet. In helpers.js, add this to the inside of the $ helper we made.

function attr(attribute, value) {
  elements.forEach(ele => {
    if (value === false) {
      ele.removeAttribute(attribute);
    } else {
      ele.setAttribute(attribute, value);
    }
  });
}

return {
  on,
  children,
  addClass,
  removeClass,
  attr,
};

Now we need to make sure this item is being added to the modal. The nice thing about having a central store is that now we only need to add another callback to get this to work. Add this to modal.js.

store.on('ITEM_ADDED', ({ items, cart }) => {
  const cartArray = [...cart];
  const cartItems = cartArray.map(itemId => modalItem(items[itemId]));
  const cartList = addClass(ul(...cartItems), 'menu');
  $('#cart-items').children(cartList);
});

Again, we are adding a callback to the ITEM_ADDED event on the store. We are grabbing the items and cart out of the store. Because the cart is a Set and those can be weird to iterate over, I am using the spread operator along with array braces to turn the Set into an array. Next, we map over the cart array and create an array of modalItems that are in the array instead. We then wrap this all in a ul with a class of menu and add it to the DOM as children of #cart-items.

Let's try this out in our browser. If you click add cart on an item, it will add it to our store, which triggers an event to fade the necessary items on the menu and add the item onto the modal. Sweet!

Now that all of that is out of the way, we are ready to implement the final piece: removing an item from the cart.

Chris Sevilleja

157 posts

Co-founder of Scotch.io. Slapping the keyboard until something good happens.