Vue.js Cart

by giovanni gokhan morkoc

HTML

<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">

	<!-- navigation bar -->
	<nav class="navbar navbar-default">
		<div class="container-fluid">
			<div class="container">
			  <a class="navbar-brand">
				  <i class="glyphicon glyphicon-shopping-cart"></i> Vue.js shoping cart
			  </a>
		  </div>
		</div>
	</nav>
	  
	<div class="container">
		<div class="row">
			<div class="col-md-4">
				<ul class="list-group">
					<li v-for="product in products" class="list-group-item">
						{{ product.name }} {{ product.price }}
						<div class="pull-right">
							<button v-show="notInCart(product)" v-on:click=" addToCart(product)" class="btn btn-xs btn-primary">
								+
							</button>
							<span v-show="!notInCart(product)" class="glyphicon glyphicon-ok-circle text-success"></span>
						</div>
					</li>
				</ul>
			</div>
			<div class="col-md-4">
				<div class="panel panel-default">
				  <div class="panel-heading">
					  <span class="glyphicon glyphicon-shopping-cart"></span>
					  Total (<span v-text="total"></span>)
				  </div>
				  <div class="panel-body">
					  <span v-show="!count" class="text-muted">Cart empty</span>
						<li v-for="item in cart_items" class="list-group-item">
							{{ item.qty }} &times; {{ item.name }} {{ item.price }}
							<div class="pull-right">
								<button v-on:click="decQty(item)" class="btn btn-xs btn-default">
									-
								</button>
								<button v-on:click="addQty(item)" class="btn btn-xs btn-default">
									+
								</button>
							</div>
						</li>
				  </div>
				</div>
			</div>
		</div>
	</div>

CSS

body {
	background-color: #f4f4f4;
}

JavaScript

var v = new Vue({
			el: 'body',
			data: {
				products: [
					{'id': 1, 'name': 'Product 1', 'price': 12.95},
					{'id': 2, 'name': 'Other product', 'price': 4.35}
				],
				cart_items: []
			},
			computed: {
				count: function() {
					return this.cart_items.length;
				},
				total: function() {
					return _.reduce(this.cart_items, function(n, cart_item) {
						return cart_item.price * cart_item.qty + n;
					}, 0).toFixed(2);
				}
			},
			methods: {
      	notInCart: function(product) {
        	var ids = _.pluck(this.cart_items, 'id');
          return !_.contains(ids, product.id);
        },
				addToCart: function(product) {
        	var cart = Vue.util.extend({}, product);
	        var ids = _.pluck(this.cart_items, 'id');
     
					if (!_.contains(ids, product.id)) {
	          cart.qty = 1;       
						this.cart_items.push(cart);
					}
				},
        addQty: function(product) {
        	product.qty = product.qty +1;
        },
				decQty: function(product) {
					product.qty -= 1;
					if (product.qty <= 0) {
						this.cart_items.$remove(product);
					}
				}
			}
		});