Build an Interactive JavaScript Food Menu: Lesson 13 of 14

Remove from Cart

Up Next

Wrapup

Autoplaying in 7 seconds!

Cancel

Now we need to remove the item from the cart. We have placed Xs to the right of every item in our modal. We need to make it so when it is clicked on, that item is removed. I think we know where we need to start. First, we need to make the ITEM_REMOVED event fire when we click the "X". Add the following to the setup_listeners.js file.

$('body').on('click', e => {
  if (e.target.classList.contains('remove')) {
    const element = e.target;
    const parent = getParentWithKey(element);
    const key = parseInt(parent.dataset.key, 10);

    parent.parentElement.removeChild(parent);
    store.trigger('ITEM_REMOVED', { item: key });
  }
});

Here we are putting an event on the body. We do this because the lis with the class remove are not there when this script first runs. We can't attach events to elements that don't exist. So instead, we attach the event to the body and filter the elements it applies to by using the e.target.classList.contains('remove') conditional. If the element originally clicked on does not have that class, nothing happens. If it does, then we get the parent with the data-key attribute like we did before and use it to fire the ITEM_REMOVED event on the store. We are also using a different way of removing an element from the DOM. Since we know its parent, we can directly just access the parent and then remove the node from the DOM. Now we need to update our state to reflect this removal. Add this to our reducer in index.js.

case 'ITEM_REMOVED':
  const newCart = (new Set(state.cart));
  newCart.delete(data.item);
  return Object.assign({}, state, {
    cart: newCart,
  });

This creates a new instance of our cart. Then it deletes the item from our new cart and assigns it to the new object we are returning from this case. Now we need to respond to this event. This time, we only need to update the menu since we are already removing the item from the list. Add the following to the menu.js file.

store.on('ITEM_REMOVED', ({ cart }) => {
  const onPageKeys = $('article.in-cart').map(ele => parseInt(ele.dataset.key, 10));
  const inCartKeys = [...cart];
  const keysToRemove = onPageKeys.filter(key => !inCartKeys.includes(key));

  keysToRemove.forEach(key => {
    $(`article[data-key='${key}']`).removeClass('in-cart');
    $(`article[data-key='${key}'] button.add-to-cart`).attr('disabled', false);
  });
});

Here, we are getting the elements that have the in-cart class added to them. These should be the ones that are also in our state. Next, we make the Set into an array. Then we filter the keys of the elements that are still faded out with the ones that are actually in our cart. We want to know if it is not in our cart. Then we loop through each of the keys. We get the article, remove its in-cart class, and remove the disabled attribute. Let's add that map helper to helpers.js.

function map(cb) {
  return elements.map(cb);
}

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

That's it! Everything should be working now. We are able to view the menu, which is entriely generated by JavaScript. We can also add and remove items from the cart. Good job!

Chris Sevilleja

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