TECRÜBEMİZİ YAZILIMCILARLA
PAYLAŞIYORUZ.
BİLGİ PAYLAŞTIKÇA ÇOĞALIR
BLOG
ASP.NET MVC & AngularJS ile Alışveriş Sepeti Uygulaması - 2
Herkese merhaba,
ASP.NET MVC & AngularJS kullanarak alışveriş sepeti yapma dersimizin 2. serisindeyiz.
Sepet görüntüleme, sepete eklemek/çıkartmak/silmek ve güncelleme gibi işlemleri yapacağız.
HomeController içerisinde Basket adında ActionResult oluşturalım.
public ActionResult Basket()
{
List<Basket> model = null; //Basket listesi
if (Session["Basket"] != null) //Session dolu ise
{
//Basket listesine Session'da bulunan Dictionary'i (sadece value'ları alarak) set et
model = ((Dictionary<Guid,
Basket>)Session["Basket"]).Select(c => c.Value)
.ToList();
}
//Son olarak ilgili sepetteki ürünleri görebilmek için model'i view'a JSON olarak dön.
return View("Basket", model:
JsonConvert.SerializeObject(model));
}
Basket.cshtml ise şöyle;
@model string
<script>
var basket = @(Html.Raw(Model));
</script>
<table class="table table-bordered table-striped
table-hover" ng-controller="BasketCtrl">
<thead>
<tr>
<th width="100">Ürün Resmi</th>
<th>Ürün Adı</th>
<th width="200">Ürün Adeti</th>
<th width="130">Ürün Fiyatı</th>
<th width="100">İşlem</th>
</tr>
</thead>
<tbody>
<!-- Sepet boş ise kullanıcıya bilgi ver -->
<tr ng-show="!basket || basket.length == 0">
<td colspan="5">
<span class="fa fa-frown-o
empty-cart"></span>
Sepetinizde ürün bulunmuyor
</td>
</tr>
<tr ng-repeat="b in basket">
<td>
<img src="~/Assets/img/{{b.Image}}" width="100" alt="{{b.Title}}" />
</td>
<td>{{b.Title}}</td>
<td>
<button type="button" ng-click="change(b.ID, 'add', $index)"
class="btn btn-sm
btn-success">
<span class="fa fa-plus"></span>
</button>
<input type="number" class="number" readonly min="0" value="{{b.Total}}" />
<button type="button" ng-click="change(b.ID, 'minus', $index)" class="btn
btn-sm btn-danger">
<span class="fa fa-minus"></span>
</button>
</td>
<td>{{b.Price | currency:''}} ₺</td>
<td>
<button type="button" ng-click="delete(b.ID, $index)" class="btn
btn-danger">
<span class="fa fa-remove"></span> SEPETTEN
ÇIKART
</button>
</td>
</tr>
</tbody>
<!-- Sepet dolu ise toplam ürün ve toplam fiyatı göster -->
<tfoot ng-show="basket && basket.length > 0">
<tr>
<td colspan="2" class="text-center">
Toplam Ürün: <strong class="color-danger">{{basket.length}} adet</strong>
</td>
<td colspan="3" class="text-right">
Toplam Tutar: <strong class="color-danger">
{{ calcTotal() | currency: '' }} ₺
</strong>
</td>
</tr>
</tfoot>
JS tarafında liste içerisinde item bulma gibi işlemleri kolay bir şekilde halledebilmek için underscore kullanacağız. Aşağıdaki adresten indirebilirsiniz. Ve _Layout.cshtml'e eklemeyi unutmayın. https://github.com/jashkenas/underscore
[HttpPost]
public ActionResult AddToBasket(Guid ID, string Type = "add")
{
//Ürün yoksa uyarı ver
if (!products.Any(c => c.ID != ID))
{
return Json(new { Status = false, Msg = "Ürün bulunamadı" },
JsonRequestBehavior.AllowGet);
}
//Type parametresinin değeri add veya minus değilse uyarı ver
else if (Type != "add" && Type != "minus")
{
return Json(new { Status = false, Msg = "Geçersiz tip!" });
}
else
{
Product product =
products.Where(c => c.ID == ID).FirstOrDefault();
//session boş ise sepette ürün yok demektir. Sepete yeni ürün olarak ekle
if (Session["Basket"] == null)
{
basket.Add(ID, new Basket()
{
ID = product.ID,
Title = product.Title,
Image = product.Image,
Price = product.Price,
Total = 1
});
Session["Basket"] = basket;
}
else
{
basket = (Dictionary<Guid, Basket>)Session["Basket"]; //session içerisindeki (sepetteki ürünleri) Dictionary<Guid, Basket> şeklinde cast edip statik basket dictionary'sine set et.
//Ürün sepette var. Adet artır ve fiyat güncelle
Basket _basket =
basket.Where(c => c.Key == ID).Select(c => c.Value)
.FirstOrDefault();
if (_basket != null)
{
//type = add ise ekle
//type = minus ise çıkart
if (Type == "add")
{
basket[ID].Total++;
basket[ID].Price = basket[ID].Total * product.Price;
}
else
{
//Ürüne ait adet sayısı 1 den büyükse azaltma işlemini yap
if (basket[ID].Total > 1)
{
basket[ID].Total--;
basket[ID].Price = basket[ID].Total * product.Price;
}
else
{
//Ürüne ait adet sayısı 1 < ise ürünü sil
basket.Remove(ID);
}
}
}
else //Ürün sepette yok. Yeni ürün olarak ekle
{
basket.Add(ID, new Basket()
{
ID = product.ID,
Title = product.Title,
Image =
product.Image,
Price =
product.Price,
Total = 1
});
}
Session["Basket"] = basket;
}
return Json(new { Status = true, Msg = "Ürün sepete eklendi", Data =
basket.Values }, JsonRequestBehavior.AllowGet);
}
Ürünü sepetten çıkartmak işlemi için; HomeController içerisinde DeleteBasket adında ActionResult oluşturalım
[HttpPost]
public ActionResult DeleteBasket(Guid ID)
{
//Ürün yoksa uyarı ver
if
(!products.Any(c => c.ID != ID))
{
return Json(new { Status = false, Msg = "Ürün bulunamadı" }, JsonRequestBehavior.AllowGet);
}
else
{
basket = (Dictionary<Guid, Basket>)Session["Basket"]; //session içerisindeki (sepetteki ürünleri) Dictionary<Guid, Basket> şeklinde cast edip statik basket dictionary'sine set et.
//basket dictionary'sinde ilgili ürün yoksa uyarı ve
if (!basket.ContainsKey(ID))
{
return Json(new { Status = false, Msg = "Sepette böyle bir bulunamadı" },
JsonRequestBehavior.AllowGet);
}
else
{
//sepette ürün varsa sil ve session'ı güncelle
basket.Remove(ID);
Session["Basket"] = basket;
return Json(new { Status = true, Msg = "Ürün sepetten silindi" },
JsonRequestBehavior.AllowGet);
}
}
}
AngularJS tarafında BasketCtrl.js isimli dosya ise şu şekilde olmalı. Gerekli açıklamaları kod içerisinde bulabilirsiniz.
app.controller("BasketCtrl", BasketCtrl); //app.js içerisinde modüle controller ekle
function BasketCtrl($scope, $rootScope,
$http, $timeout) {
$scope.basket = basket;
$scope.change = (id, type, index) => { //id parametresi, type parametresi ve ürünün saklandığı indis değeri
$http.post("/Home/AddToBasket", { ID: id,
Type: type }).then(resp => {
var data = resp.data;
const product = _.findWhere(data.Data, {
ID: id }); //underscore ile gelen listede ürünü bul
if (product) { //ürün varsa
var total = 0; //sepetteki ürün sayısını 0 olarak güncelle
$scope.basket.forEach(b => { //sepetin listelendiği listede dön ve içerisindeki (ürün adeti ile ürün fiyatını yenileri ile güncelle)
if (b.ID === product.ID) {
b.Total =
product.Total;
b.Price =
product.Price;
}
total += b.Total; //sepetteki ürün sayısını gelen data içerisindeki toplam adet ile güncelle
});
/*
broadcast'ler ile bir değeri başka bir controller'a aktarmak için kullanılır.
sayfanın en üst sağ kısmında bulunan sepetteki ürün sayısını ProductCtrl içerisinde $scope.total değişkeni ile gösteriyorduk.
totalReceived isminde bir broadcast yayını yaptık ve değer olarak total değişkenini gönderdik.
Bunu ProductCtrl'da karşıladık.
*/
$rootScope.$broadcast("totalReceived", total);
} else { //ürün yoksa sepetten silinmiş demektir. basket listesinden ürünü sil
$scope.basket.splice(index, 1);
}
});
};
$scope.calcTotal = () => {
if ($scope.basket && $scope.basket.length > 0) {
var total = 0;
$scope.basket.forEach(d => {
total += d.Price;
});
return total;
}
};
$scope.delete = (id, index) => { //id parametresi, ürünün saklandığı indis numarası
$http.post("/Home/DeleteBasket", { ID:
id }).then(resp => {
var data = resp.data;
$scope.basket.splice(index, 1);
var total = 0; //sepetteki ürün sayısını 0 olarak güncelle
$scope.basket.forEach(b => { //sepetin listelendiği listede dön ve içerisindeki (ürün adeti ile
ürün fiyatını yenileri ile güncelle)
b.Total = b.Total;
b.Price = b.Price;
total += b.Total; //sepetteki ürün sayısını gelen data içerisindeki toplam adet ile güncelle
});
$rootScope.$broadcast("totalReceived", total);
alert(data.Msg);
});
};
}
Broadcast yayını yaptıktan sonra ProductCtrl.js dosyasında bunu karşılamak için aşağıdaki kodu ekliyoruz.
$scope.$on("totalReceived", (e, total) => { //gelen broadcast yayını dinle ve gelen değeri $scope.total değişkenine ata
$scope.total = total;
});
Bir serinin daha sonuna geldik. Başka serilerde görüşmek üzere.