Only the first object from the Angular array is retrieved

Viewed 37

I need your help. I'm practicing Angular and trying to pass data between components using rxjs. I have 2 components and a service. I'm getting data from an API. My code works, but it's not correct. I manage to get the object from the array and transfer it, but unfortunately, only the first element of the array is extracted. Please tell me how to get different objects by clicking on the button, and not just the first one? Thank you very much

Service

export class CheckboxServiceService {

   public allSelectedProducts: BehaviorSubject<ProductModel[]> = new BehaviorSubject<ProductModel[]>([])

   sendProductToList(product: any) {
      this.allSelectedProducts.next(product);
   }
}

ComponentSender

export class ProductsListApiComponent implements OnInit {

   products: ProductModel[];
   productDifferent: any;

   constructor(private apiService: ApiService , private checkboxService: CheckboxServiceService) { }

   ngOnInit(): void {
      this.apiService.getAllProducts().subscribe(value => this.products = value);
   }

   addProductToList() {
      let currentValue = this.checkboxService.allSelectedProducts.getValue();
      this.productDifferent = this.products.find(element => element.id);
      currentValue.push(this.productDifferent);
      this.checkboxService.sendProductToList(currentValue);
   }
}

ComponentReceiver

export class ProductsRecieverComponent implements OnInit {

    public selectedProductsList: ProductModel[] = [];

    constructor(private checkboxService: CheckboxServiceService) { }

    ngOnInit(): void {
      this.checkboxService.allSelectedProducts.subscribe(value => {
       this.selectedProductsList = value;
    })
   }
}
1 Answers

The problem lies in the sendProductToList method. Indeed, you're only emitting one product, rather than adding a new product to the product list.

sendProductToList(product: any) {
  this.allSelectedProducts.next(product);
}

By calling next passing a single product, you're always emitting a single product, they won't "accumulate".

Besides that, most times you don't want to expose a BehaviorSubject as a public member of your service, but rather an Observable, since the first supports read and write operations while the latter is readonly, preventing clients from using your service the wrong way.

Hence, this should fix it.

export class CheckboxService {
  public products$: Observable<Product[]>;
  private productsSubject: BehaviorSubject<Product[]>;

  constructor() {
    this.productsSubject = new BehaviorSubject([]);
    this.products$ = this.productsSubject.asObservable();
  }

  sendProductToList(product: Product) {
    const products = this.productsSubject.value;
    const updatedList = [...products, product);
   
    this.productsSubject.next(updatedList);
  }
}
Related