Component’ ler arası veri paslamaya pek çok defa ihtiyaç duyarız. Nested(iç-içe) component arası veri paslanmasını https://gelistir.net/340/angular-componentler-arasi-veri-paslama/ adresinde incelemiştik. Input ve Output ile gerçekleştiriyorduk. Lakin Cross Component’ ler arası veri paslamak daha farklı bir pratik gerektiriyor.

Cross Component Nedir ?

Nested Component’ ler gibi aynı hiyerarşi altında OLMAYAN component’ lerdir. Örneğin, Header, Content, footer vb. gibi.

Uygulama Senaryosu;

  • AppComponent: Ana Component
  • Header Component: Ürün sepetindeki ürünlerin sayısını gösteren;
    ng g c header
  • Category Component : Ürünleri listeleyen;
    ng g c category
  • BasketService : Ürün ekleme, çıkarma işlemlerini gerçekleştiren;
    ng g s services/basket
  • CategoryComponent‘ te listelenen ürünleri, BasketService üzerinden sepete eklediğimizde, HeaderComponent‘ te gösterilen ürün sayısı güncellenecek. Bu 2 cross component arasındaki veri iletişimi BasketService üzerinden, event tetikleme ile sağlanacak. EventEmitter kütüphanesi bize bu imkanı tanıyor.

Service direk olarak AppModule’ de inject edilmiş durumda olacağı için, tüm component ler tarafından görülebilir durumda olacak.

BasketService

import { Injectable } from '@angular/core';
import { EventEmitter } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class BasketService {

  basket = [];

  basketUpdated = new EventEmitter<number>();

  constructor() { }

  addProduct(product) {
    this.basket.push(product);
    this.basketUpdated.emit(this.basket.length);
  }

}
  • basket adında bir dizi oluşturuyoruz, sepete atılan ürünleri tutan.
  • basketUpdated adında bir event oluşturuyoruz. number veri-tipinde argüman yollayan.
  • addProduct metodu, product objesi alıyor, basket dizisine ekliyor ve ardından basketUpdated event’ ini "emit" metodu ile tetikliyor. Tetiklerken, sepetteki ürünlerin sayısını da argüman olarak yolluyor.

CategoryComponent

import { Component } from '@angular/core';
import { BasketService } from '../services/basket.service';

@Component({
  selector: 'app-category',
  templateUrl: './category.component.html',
  styleUrls: ['./category.component.css']
})
export class CategoryComponent {

  constructor(private basketService: BasketService) { }

  products = [
    {
      name: 'telefon',
      price: 105,
      id: 10
    },
    {
      name: 'kulaklık',
      price: 30,
      id: 11
    }
  ];

  addToBasket(product) {
    this.basketService.addProduct(product);
  }

}
  • products ismindeki dizi ürünleri barındırıyor.
  • addToBasket metodu, template’ den tetikleniyor, ilgili ürünü parametre olarak alıyor ve constructor’ da dependency injection yapmış olduğumuz BasketService’ in addProduct metoduna gönderiyor.

CategoryComponent Template;

<div class="row">

<h1>Elektronik Kategorisi</h1>

<div class="panel-group">

        <div class="panel panel-default" *ngFor="let product of products">

          <div class="panel-body">

            <p>{{product.name}} - {{product.price}} TL</p>

            <button type="button" class="btn btn-success" (click)="addToBasket(product)">Sepete Ekle</button>

          </div>

        </div>

</div>

</div>
  • Component’ te tanımlanmış product dizisindeki ürünleri listeliyor. Her ürün’ ün addToBasket metodunu tetikleyen butonu var.

HeaderComponent;

import { Component } from '@angular/core';
import { BasketService } from '../services/basket.service';

@Component({
  selector: 'app-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.css']
})
export class HeaderComponent {

  basketCount: number;

  constructor(private basketService: BasketService) {
    this.basketService.basketUpdated.subscribe(
      (count: number) => this.basketCount = count
    );
  }

}
  • basketCount adında, sepetteki toplam ürün bilgisini tutan bir değişkene sahip.
  • constructor aşamasında, BasketService’ in basketUpdated event’ ine subscribe oluyor, bu sayede ilgili event her tetiklendiğinde, bilgisi ulaşıyor ve event’ in sağladığı count değeri ile, basketCount değerini belirliyor.

CrossComponent’ ler arası iletişimi bu şekilde sağlamış olduk.

HeaderComponent Template;

<nav class="navbar navbar-inverse">

        <div class="container-fluid">

          <div class="navbar-header">
            <a class="navbar-brand" href="#">Shop</a>
          </div>

          <ul class="nav navbar-nav navbar-right">
            <li>
                <a href="#"><span class="glyphicon glyphicon-shopping-cart"></span>
                   <span *ngIf="basketCount > 0">( {{basketCount}} )</span>     
                </a>
            </li>
          </ul>

        </div>

</nav>
  • Boostrap’ in hazır navbar’ ını kullandık. İncelememiz gereken yer, ngIf kontrolü ile, basketCount değerini takip edilmesi ve 0 dan büyük ise, string interpolation yöntemi ile basılması.

AppComponent Template;

<div class="container">

  <app-header></app-header>

  <div class="row">

    <app-category></app-category>

  </div>

</div>
  • Ana template’ imize önce HeaderComponent’ i ardından AppComponent’ i ekledik.

CANLI ÖRNEK;

  • ürünleri sepete ekleyip, header daki sayının arttığını inceleyebilirsiniz.
Last modified: 17 November 2019

Author

Comments

Write a Reply or Comment

Your email address will not be published.