Angular 4 - Örnek Sepete Ekle Uygulaması - Yazılım Mimarileri ve Tasarım Desenleri Üzerine

Angular 4 – Örnek Sepete Ekle Uygulaması

Merhaba,

Angular 4 yazı dizimizde şuana kadar incelemiş olduğumuz tüm yapıları bütünsel olarak değerlendirmemizi sağlayacak örnek bir uygulama yapma zamanının geldiğini düşünüyorum. Başlıktan da anlaşılacağı üzere bu örnek uygulamamız sepete ekleme işlemi üzerine kurgulanacaktır.

Bu makalede hedeflenen kazanım, şurada bulunan Angular yazı dizimizin şuana kadar olan 20 makalelik kısmında incelediğimiz konuları pekiştirmek, bu dizinin şu anki seviyesinde bir Angular projesinin tadına varmak ve bütünsel olarak component, modül vs. gibi yapıların Third Party paketlerle birlikte kullanımını pratiksel olarak uygulamaktır.

O halde hiç vakit kaybetmeden örnek uygulamamızın inşasına başlayalım.

Third Party Paketlerin Entegrasyonu

İlk olarak kullanacağımız third party paketler olan bootsrap, jQuery vs. gibi yapıların projeye entegrasyonunu şuradaki makalede ele aldığımız gibi sağlayalım.

Entity ve Veri Kaynaklarının Oluşturulması

Şimdi sıra sepete eklenecek ürünlerin modeli ve veri kaynaklarıyla birlikte sepetteki her bir ürün için sepet bilgisi tutacak olan sepet modelini ve listesini oluşturmaya geldi.
Ürün modeli;

export class Product {
    id: number;
    productName: string;
    price: number;
    stock: number;
}

Ürün veri kaynağı;

import { Product } from "./product";

export const ProductList: Product[] = [
    { id: 1, price: 100, stock: 50, productName: "Mouse" },
    { id: 2, price: 200, stock: 10, productName: "Monitör" },
    { id: 3, price: 4500, stock: 3, productName: "Televizyon" },
    { id: 4, price: 600, stock: 25, productName: "Kasa" },
    { id: 5, price: 120, stock: 17, productName: "Klavye" },
    { id: 6, price: 489, stock: 21, productName: "Ekran Kartı" },
    { id: 7, price: 699, stock: 28, productName: "İşlemci" },
    { id: 8, price: 55, stock: 13, productName: "Fan" }
];

Sepet modeli;

import { Product } from "./product";

export class Basket {
    quantity: number;
    product: Product;
}

Sepet modelimize dikkat ederseniz eğer içerisinde ilgili üründen sepette kaç adet olduğu bilgisini verecek “quantity” ile ilgili ürünün nesnesini tutacak “product” özellikleri mevcuttur.

Sepet listesi modeli;

import { Basket } from "./basket";

export const BasketList: Basket[] = [];

Servis Oluşturulması

Şimdi veri kaynağımıza erişebilmek, veri ekleyebilmek yahut silebilmek vs. gibi işlemler için servis oluşturmamız gerekmektedir.

İlk olarak sepetteki işleyişi yönetecek servisimizi oluşturalım.

import { Injectable } from '@angular/core';
import { Product } from "../entitys/product";
import { BasketList } from "../entitys/basket-list";
import { Basket } from '../entitys/basket';
@Injectable()
export class BasketService {
  constructor() { }
  getBasketList(): Basket[] {
    return BasketList;
  }
  addProductBasket(product: Product) {
    var productContains = BasketList.find(p => p.product.id == product.id);
    if (productContains)
      productContains.quantity += 1;
    else {
      let basket = new Basket();
      basket.product = product;
      basket.quantity = 1;
      BasketList.push(basket);
    }
  }
  clearBasket() {
    BasketList.splice(0, BasketList.length);
  }
  removeProductBasket(product: Product) {
    var productContains = BasketList.find(p => p.product.id == product.id);
    if (productContains) {
      var productIndexNo = -1;
      productIndexNo = BasketList.indexOf(productContains);
      if (productIndexNo != -1)
        BasketList.splice(productIndexNo, 1);
    }
  }
}

Servisimizin içeriğine göz atarsanız eğer sepet ekleme ve silme işlemlerinin yapıldığı fonksiyonları göreceksiniz. Bu fonksiyonlar, isimlerinden ve işlevlerinden gayet net olduklarından dolayı fazla detaya girmemekteyim.

Şimdi ise ürünlere kaynak teşkil edecek servisi oluşturalım.

import { Injectable } from '@angular/core';
import { Product } from '../entitys/product';
import { ProductList } from '../entitys/product-list';

@Injectable()
export class ProductService {
  constructor() { }
  getProductList(): Product[] {
    return ProductList;
  }
}

Componentlerin Oluşturulması ve Viewların Tasarlanması

Sıra componentlerin oluşturulmasına geldi.
İlk olarak ürün veri kaynağını listeleyeceğimiz componentimizi oluşturalım.

import { Component, OnInit } from '@angular/core';
import { Product } from '../entitys/product';
import { ProductService } from '../services/product.service';
import { BasketService } from '../services/basket.service';

@Component({
  selector: 'app-product',
  templateUrl: './product.component.html',
  styleUrls: ['./product.component.css']
})
export class ProductComponent implements OnInit {
  productList: Product[];
  constructor(private productService: ProductService, private basketService: BasketService) { }
  ngOnInit() {
    this.productList = this.productService.getProductList();
  }
  addProductBasket(product: Product) {
    this.basketService.addProductBasket(product);
  }
}

Ve ardından bu componentin viewini oluşturalım.

<div class="list-group-item" style="width: 225px;">
  <a *ngFor="let product of productList" href="#" class="list-group-item list-group-item-action flex-column align-items-start" (click)="addProductBasket(product)">
    <div class="d-flex w-100 justify-content-between">
      <h5 class="mb-1">{{product.productName}}</h5>
      <small>{{product.price | currency}}</small>
    </div>
    <p class="mb-1">Stok : {{product.stock}}</p>
    <button type="button" class="btn btn-primary">Sepete Ekle</button>
  </a>
</div>

Dikkat ederseniz click eventına bağlanan “addProductBasket” fonksiyonu ile sepete yeni bir ürün eklenmektedir.

Şimdi de sepet componentini oluşturalım.

import { Component, OnInit } from '@angular/core';
import { Basket } from '../entitys/basket';
import { BasketService } from '../services/basket.service';
@Component({
  selector: 'app-basket',
  templateUrl: './basket.component.html',
  styleUrls: ['./basket.component.css']
})
export class BasketComponent implements OnInit {
  basketList: Basket[];
  basketCount: number;
  constructor(private basketService: BasketService) { }
  ngOnInit() {
    this.basketList = this.basketService.getBasketList();
    this.basketCount = this.basketService.getBasketList().reduce((a, b) => a = a + b.quantity, 0);
  }
}

Vee tabi ki de viewini unutmayalım.

<div style="width: 225px;float: right;">
  Sepetteki Ürün Sayısı : {{basketCount}}
  <ul class="list-group" *ngFor="let basket of basketList">
    <li class="list-group-item">{{basket.product.productName}} -
      <span class="badge">{{basket.quantity}}</span>
    </li>
  </ul>
</div>

Tüm bu inşalardan sonra oluşturulan componentlerin declarasyonu ve servislerin projede global erişilebilir olması için ana modülümüz olan “app.module.ts” dosyasına gelelim ve aşağıdaki çalışmayı gerçekleştirelim.

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { ProductComponent } from './product/product.component';
import { BasketComponent } from './basket/basket.component';
import { ProductService } from './services/product.service';
import { BasketService } from './services/basket.service';
@NgModule({
  declarations: [
    AppComponent,
    ProductComponent,
    BasketComponent
  ],
  imports: [
    BrowserModule
  ],
  providers: [ProductService, BasketService],
  bootstrap: [AppComponent]
})
export class AppModule { }

Ve son olarak ana componentimiz olan “app.component.html” dosyasına componentlerimizin seçicilerini etiket olarak ekleyelim.

<app-basket></app-basket>
<app-product></app-product>

DoCheck Interface’inin Uygulanması

“product” componenti sayesinde “BasketList” içerisinde olacak tüm değişiklikleri “basket” componenti içerisinde takip edebilmek için DoCheck Interface‘ini kullanacağız.

Bu interface, ilgili componentin uygulama boyunca ilişkisi olan tüm verilere subscribe olmakta ve bu verilerde olası değişiklikler ceyran ederse ngDoCheck fonksiyonunu tetiklemektedir.

Doğal olarak “basket” componentimizin içeriğini bu interfaceden türeterek güncelleyelim.

import { Component, OnInit, DoCheck } from '@angular/core';
import { Basket } from '../entitys/basket';
import { BasketService } from '../services/basket.service';
@Component({
  selector: 'app-basket',
  templateUrl: './basket.component.html',
  styleUrls: ['./basket.component.css']
})
export class BasketComponent implements OnInit, DoCheck {
  basketList: Basket[];
  basketCount: number;
  constructor(private basketService: BasketService) { }
  ngOnInit() { }
  ngDoCheck() {
    this.basketList = this.basketService.getBasketList();
    this.basketCount = this.basketService.getBasketList().reduce((a, b) => a = a + b.quantity, 0);
  }
}

Dikkat ederseniz eğer ngOnInit eventındaki tüm işlemleri ngDoCheck eventına almış bulunmaktayız. Bunun sebebi yukarıda anlatmaya çalıştığım mantıkla paralel şekilde “BasketList” üzerinde yapılan tüm değişikler neticesinde tekrardan ilgili işlemlerin tetiklenmesini sağlamaktır.

Angular Notifications Entegrasyonu

Şimdide sepete ekleme işleminin başarıyla sonuçlandığını kullanıcıya gösterebilmek için Angular Notifications paketinden yararlanacağız. Bu paketin entegrasyonu için şuradaki makaleden faydalanabilirsiniz.

Hemen “product” componentinde notifications ile ilgili düzenlemeleri yapalım.

import { Component, OnInit } from '@angular/core';
import { Product } from '../entitys/product';
import { ProductService } from '../services/product.service';
import { BasketService } from '../services/basket.service';
import { NotificationsService } from 'angular2-notifications';

@Component({
  selector: 'app-product',
  templateUrl: './product.component.html',
  styleUrls: ['./product.component.css']
})
export class ProductComponent implements OnInit {
  productList: Product[];
  constructor(private productService: ProductService, private basketService: BasketService, private notifications: NotificationsService) { }
  public notificationOptions = {
    timeOut: 3000,
    position: ["bottom", "right"],
    lastOnBottom: true
  };
  ngOnInit() {
    this.productList = this.productService.getProductList();
  }
  addProductBasket(product: Product) {
    this.basketService.addProductBasket(product);
    this.notifications.success("Ürün sepete başarıyla eklenmiştir.", product.productName + " sepete eklenmiştir.");
  }
}

Ardından bu düzenlemeyi viewde de gerçekleştirelim.

<div class="list-group-item" style="width: 225px;">
  <a *ngFor="let product of productList" href="#" class="list-group-item list-group-item-action flex-column align-items-start"
    (click)="addProductBasket(product)">
    <div class="d-flex w-100 justify-content-between">
      <h5 class="mb-1">{{product.productName}}</h5>
      <small>{{product.price | currency}}</small>
    </div>
    <p class="mb-1">Stok : {{product.stock}}</p>
    <button type="button" class="btn btn-primary">Sepete Ekle</button>
  </a>
</div>
<simple-notifications [options]="notificationOptions"></simple-notifications>

Evet arkadaşlar. Bu işlemden sonra projemizi kaydedip, yayınladığımızda karşımıza aşağıdaki gibi bir sepet uygulaması gelmektedir.
Angular 4 - Örnek Sepete Ekle Uygulaması

Umarım faydasını bulacağınız ve size yol gösterici bir uygulama ve içerik oluşturmuşuzdur.

Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar…

Örnek çalışma projesini Angular CLI ile oluşturduğumdan dolayı yaklaşık 400 MB’lık bir proje meydana gelmiş bulunmaktadır. O yüzden ilgili çalışmanın kaynak kodlarına erişmek istiyorsanız eğer konu altına yorum yazmanız yeterli olacaktır.

Bunlar da hoşunuza gidebilir...

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

*

Copy Protected by Chetan's WP-Copyprotect.