Series: Building a Shopping Cart

Shopping Cart Part 1-Basics

Published on Aug 31, 2016

This is the start of our series on Shopping Carts- a vital part of any ecommerce site.

In this video we create the cart service, add buy and remove buttons, make a basic checkout page, and learn about the query method.


Links

Code

//services/cart.js
import Ember from 'ember';

export default Ember.Service.extend({
  store: Ember.inject.service(),
  monsterIds: [1, 2],
  monsters: Ember.computed('monsterIds.[]', function(){
    let monsterIds = this.get('monsterIds');
    return this.get('store').query('monster', {ids: monsterIds})
  }),
  add(monsterId){
    this.get('monsterIds').addObject(monsterId);
  },
  remove(monsterId){
    this.get('monsterIds').removeObject(parseInt(monsterId));
  }
});
//templates/checkout.hbs
<div class="cart">
  {{#each cart.monsters as |monster|}}
    <div class="cart-item">
      <div class="image">
        <img src={{monster.imageUrl}} />
      </div>
      <div class="details">
        {{monster.name}}
        <br>
        ${{monster.price}}
      </div>
      <button {{action 'removeItem' monster.id}}>Remove</button>
    </div>
  {{/each}}
</div>
//controllers/checkout.js
import Ember from 'ember';

export default Ember.Controller.extend({
  cart: Ember.inject.service(),
  actions: {
    removeItem(monsterId){
      this.get('cart').remove(monsterId)
    }
  }
});
//app.css

.cart {
  font-size: 18px;
}

.cart-item {
  padding-top: 20px;
}
.cart-item .image {
  float: left;
  width: 50px;
  height: 70px;
  margin-right: 20px;
}
.cart-item img {
  width: 100%;
}
//application.hbs
<div class="pull-right">
  {{#link-to 'checkout'}}Shopping Cart: {{cart.monsterIds.length}} Items{{/link-to}}
  &nbsp;&nbsp;&nbsp;
  //... right-navbar stuff
</div>
//... left-navbar stuff

Don't forget to inject cart into controllers/application.js

//templates/monsters/monster/index.hbs

//...portrait
<button class="btn" {{action 'buyItem'}}>
  Buy Plushy
</button>
//...other buttons
//controllers/monsters/monster/index.js
import Ember from 'ember';

export default Ember.Controller.extend({
  cart: Ember.inject.service(),
  actions: {
    buyItem(){
      this.get('cart').add(this.get('model.id'));
    }
  }
});

Transcript

Today we’re starting our series on shopping carts. So you’ve probably seen a shopping cart before on various e-commerce websites. You add something to the cart and then in the top right corner there’s a cart with a number, and you click on it and it’ll take you to a page that shows everything that’s in your cart, then it gives you the option to buy the things that are in your cart. So you should have a pretty good idea whether your app needs this or not. But even if you don’t specifically need a cart, stick around because we’re going to be showing some cool stuff with services and local storage.

On the other side of the spectrum if you’re in a huge rush just to get your cart put in your app really quick, then there’s the ember-cart addon. It’s a great way to get started and a great set of primitives to build on. But the documentation for customization isn’t quite there yet. It has good documentation for basic use, but if you want to change things then you have to look into the source code. And it’s not 1.0 yet, so beware. And if you listen to the rest of this episode, it’ll help you understand this addon as well.

So the app we’re going to be working with today is the monetized version of our monsters demo. So each of these monsters as you can see has a price tag already, and we’re going to be selling plushiess of these monsters. So let’s start by generating a service called cart. And while we’re here, we’ll go ahead and generate a route called checkout, and we’ll generate a controller for that route as well. The core of the cart service will be an array called monsterIds. And we’re keeping track of the ids instead of the monsters themselves so that if the price changes or anything else changes about the monster after they put it into the cart, then their checkout will be updated with the new information instead of holding on to the old information.

So it’s going to revolve around this array. We’ll go ahead and seed it with a couple of monsters so we can see how things are looking. And then of course we’re going to want to translate those monsterIds into actual monsters, and that’ll be a computed property based on the monsterIds. So in this function, we’re going to call to the server. We have to do that because we can’t be entirely sure that these monsters are already in the data store. So we’ll call the server using the query function. And what that’ll do is that’ll send an array of ids, and then the server would turn back to us a json array that ember data will translate back into monster models.

Of course you have to make sure that your server will give you back what you expect. This is doing that correctly, but previously it was just returning all of the monsters no matter whether I passed it ids or not. So you may have to go in and edit your server if you’re using query.

So this should be enough to let us display some of the monsters in the cart. So let’s go to our checkout controller and then we’ll inject the cart service. That will allow us to loop over the monsters like so. Then for the monster display code, I’ll go ahead and paste in some template code and then wrap it all in a div with the class of cart. Then we’ll paste in some css as well. It’s not particularly good or important css, so we won’t dwell on it, but it does make our monsters display decently. We’ll come back to this page soon, but now that we have a way to display the monsters in the cart, let’s go about adding monsters to the cart.

How we’ll do that is on the monster show page next to ‘Add to team’ and ‘Edit’, we’ll have a ‘Buy Plushy Button’. We’ll do that by copying the buttons that are there and then just changing a couple of things. We have the buyItem action which we’ll go ahead and add to the controller, and then this action will call the cart and we’ll call add on the cart, and then give the id of the monster we’re adding. Now that means that the cart service is going to have to have an add function and it’s going to take a monsterId. And how we’re going to use this, is we’re going to get to the monsterIds, and we’re going to addObject with the new monsterId.

So now we can hit this button, and if go and find this service and inspect it, then we’ll see that it did indeed get added. There now is another monster id in there. Of course, we can’t expect our users to use the ember inspector to tell whether they've added something to their cart, so we’re going to add up here in the top right a cart link that lists the number of items in the cart. So we’ll start off with a link, and this link will be to the checkout route. Then inside that link we’ll have some basic text, and then for the length we’ll grab the monsterIds array from the cart and get the length of it. And of course for this to work, we have to go to the controller for the application and inject the cart service. Then for styling purposes, we’ll go ahead and put in some ASCII spaces. Then we’ll see that... lookie there, it says that we have two items. Those are the two items that we have in there by default. And when we buy this plushy, now it says three items. We go to the shopping cart and it’ll show all of them. A little overcrowded, but that’ll be fixed in a second.

Alright. Now we have ways to add and display our items in the shopping cart. Now we want to be able to remove items once they’re in the shopping cart. We don’t want to be stuck buying them once we hit the ‘Add’ button. We will have a button and the action will be removeItem, and then we’ll pass in the monster.id and the text will simply be removed. Then in the checkout controller, we’ll add an actions hash, and we’ll have the removeItem action that’ll take the monsterId. This action will just pass stuff up to the cart, so we’ll have the remove function called. And that remove function is not written yet, but it bears a striking similarity to this add function, except instead of being called add, it’s called remove, and instead of addObject, it’s removeObject. And we’ll also have to make sure that the id that we’re passing in is an integer, so we’ll use parseInt. Now this should be enough to get us removing the monsters. And there we go. And you can see it’s reflected in saying there’s only one item in the cart.

Alright, we’ve made some pretty great progress today. But this episode is getting really long, so we’re going to cut it. And in the next episode, we’re going to add some really cool features. So the biggest one of those is when you reload the page, it doesn’t reset your cart. Being able to keep the cart between page loads is really nice, and the great thing is we won’t even have to 08:46 to the database to do it. We’re going to use local storage. The second thing is being able to remove everything in the cart at once, being able to clear the cart. And another is having all the items in the cart added up to a total. So we’re going to tackle all that and maybe even fix a bug or two. So I’ll see you there.

Building a Shopping Cart

Subscribe to our mailing list