vanessa
vanessa

Reputation: 13

Angular: Retrieve count directly from a service

I have a cart-service and 2 components. The product-list component displays the products with a buy button. The top-bar component should display the count but it doesn't work if I getItemCount() directly. What's the issue? I want to get the length/count and not the entire array. Thanks for the help!!!

I also have the code on stackbliz.

@Component({
  selector: 'app-top-bar',
  template: `
    Item Count: {{ itemCount }}<br>
    Items: {{ items | json }}
  `
})
export class TopBarComponent implements OnInit {
  itemCount: number = 0;
  items: string[] = [];

  constructor(private cartService: CartService) { }

  ngOnInit() {
    this.items = this.cartService.getItems();
    this.itemCount = this.cartService.getItemCount();
  }
}
@Component({
  selector: 'app-product-list',
  template: `
    <div>
      <button (click)="addToCart('New Stuff')">Buy</button>
    </div>
  `
})
export class ProductListComponent {
  products: string[];

  constructor(private cartService: CartService) { }

  addToCart(item: string) {
    this.cartService.addItem(item);
  }
}
export class CartService {
  private items: string[] = [ 'One', 'Two'];

  getItems(): string[] {
    return this.items;
  }

  getItemCount(): number {
    return this.items.length;
  }

  addItem(item: string) {
    this.items.push(item);
  }
}

Upvotes: 1

Views: 520

Answers (2)

Supun De Silva
Supun De Silva

Reputation: 1487

Improving my answer

I believe this is a better approach

Cart Service

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
@Injectable({
  providedIn: 'root'
})
export class CartService {
  //  Define behavior Sub
  public valueObservable: BehaviorSubject<number> = new BehaviorSubject<number>(0); 
  private items: string[] = [ 'One', 'Two'];

  //  Init at ctor
  constructor() {
    this.valueObservable.next(this.items.length);
  }

  getItems(): string[] {
    return this.items;
  }

  getItemCount(): number {
    return this.items.length;
  }

 addItem(item: string) {
    this.items.push(item);

    //  Notify on change
    this.valueObservable.next(this.items.length);
  }
}

TopBarComponent

    export class TopBarComponent implements OnInit, OnDestroy {
    itemCount: number = 0;
    items: string[] = [];
    private serviceSubsription ;
    constructor(private cartService: CartService) { }

    ngOnInit() {
        this.items = this.cartService.getItems();

        this.itemCount = this.cartService.getItemCount();

        this.serviceSubsription = this.cartService.valueObservable.subscribe(
        value =>  { this.itemCount = value; console.log('Value : ' + value); }
        );
    }

    ngOnDestroy() {
        this.serviceSubsription.unsubsribe()
    }
}

Upvotes: 3

Supun De Silva
Supun De Silva

Reputation: 1487

In the Top Bar Component, Instead of calling the this.cartService.getItemCount() in the onInit

Change the template to look as follows

template: `
Item Count: {{ cartService.getItemCount()}}<br>
Items: {{ items | json }}
`

Becomes an observeable to the DOM

Upvotes: -1

Related Questions