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 }} × {{ 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);
}
}
}
});