1
votes

I am learning rxjs and I guess I am doing something wrong as my BehaviourSubject is emitting value only once.

In my Service -

private cartItemCount = new BehaviorSubject<Observable<Number>>(this.getCartItemsCount());
actualCartItemCount=this.cartItemCount.getValue();

getCartItemsCount(){
return this.http.get<Number>('/api/getCartItemsCount/'+this.getCartID());
}

Below Method is also in above service for Add or Remove Product but will be called from ProductCartComponent and inside I am calling Behaviour Subject next method

private updateProductCart(cartID:string,productId:number,change:string){
this.cartItemCount.next(this.getCartItemsCount());
return this.http.get<Item>('api/updateProductItem/'+cartID+'/'+productId+'/'+change);
}

Now in my NavBar Component I am subscribing to actualCartItemCount Observable

constructor( private cartService:ShopingCartService)
 { }

ngOnInit() {
this.cartService.actualCartItemCount.
subscribe(res => {this.totalCartItemCount = res;
}

In the console I can see getCartItemsCount will be called whenever add or remove is happening but in NavBar Component where I have subscribed to the actualCartItemCount is being called only once.

Kindly guide me and let me know if more details are required on this...

1
My guess is that you have two different instances of the service. Show us how and where you have provided the service (i.e. where you have providers: [ShopingCartService]. - JB Nizet
In app.module.ts i have the following array and all the services are mentioned like this - providers: [SignUpService, ShopingCartService, AuthGuard, LoginGuard,{ provide:HTTP_INTERCEPTORS, useClass:AuthInterceptor, multi:true }], - Arpan Sharma
you might be destroying the subscription somewhere like in ngDestroy or something so that it is not getting - Sravan
In this.cartItemCount.getValue() you have the returned value from this.getCartItemsCount() which is created only once. Then subscribing this.cartService.actualCartItemCount is subscribing to this.http.get and not the BehaviorSubject. - martin
yes @martin you are correct... i couldn't use .asObservable on this.cartItemCount as it was already Observable<Number> so i went ahead with that.. - Arpan Sharma

1 Answers

0
votes

First, read the component interaction guide thoroughly.

If NavBar is always there in the view you wouldn't require a BehaviorSubject, simple Subject can do.

import { Injectable } from '@angular/core';
import { Subject }    from 'rxjs';

@Injectable()
export class CartService {

  // Observable number sources
  private countSource = new Subject<number>();

  // Observable number streams
  count = this.countSource.asObservable();

  // Service message commands
  updateCount(count: number) {
    this.countSource.next(count);
  }
}

In NavBar you can use the observable directly in template using async pipe:

@Component({
  selector: 'app-nav-bar',
  template: `Count : {{cartService.count | async}}`
})
export class NavBarComponent {
  constructor(private cartService: CartService) {}
  }

In Product Cart, you can update the new count like shown below, it will update the value in NavBar, or any other places:

@Component({
  selector: 'app-product-cart',
  template: `
  `
})
export class ProductCartComponent {
  constructor(private cartService: CartService) {}
  /**
  Update count in the shared service and thus in NavBar
  */
  private updateCartCount(count: number){
     this.cartService.updateCount(count);
  }
  }