Search code examples
angulartypescriptrxjsobservablerxjs-observables

RXJS, how to change the result of each result from an observable?


I have this reloadProducts function that i use to reload the products i have in my cart. I have 2 models, one is CartProduct and the other a Product. The CartProduct has a name which i use with a function from my service, to get the matching Product.

Now when i map the cartProduct, i want to check if that CartProduct has a boolean (mixMatch) set to true, if so then set the Products mixMatch boolean to true and false if not. In the code below i commented #HERE with where i gave my try on it, but it's not working.

Can anyone help me or guide me in any direction on how to do this?

  @HostListener('window:storage')
  reloadProducts() {
    this.cartProducts = Array.from(this.cartService.getProducts());
    this.products = undefined;
    this.totalPrice = undefined;
    this.producers = undefined;
    this.producerNames = [];
  
    forkJoin(
      this.cartProducts.map(cartProduct => {
        let result = this.productService.getProduct(cartProduct.product_name);
         // HERE
        result.subscribe((product) => {
          if (cartProduct.mixMatch) {
            product.mixMatch = true;
          }
          else if (!cartProduct.mixMatch) {            
            product.mixMatch = false;
          }
        })
        return result;
      }
      )
    ).pipe(
      switchMap(productListDto => {
        productListDto.map(product => {
          if (this.producerNames.indexOf(product.producer_name) === -1) {
            this.producerNames!.push(product.producer_name)
          }
        })
        this.products = productListDto
        this.mixMatchProducts = productListDto.filter(p => p.mixMatch)

        return forkJoin(
          this.producerNames.map(producerName => this.producerService.getProducerByName(producerName))
        )
      })
    ).subscribe(producers => this.producers = producers)
    this.fetchTotalPrice();
    
  }

Solution

  • You want to have the function form part of the rxjs pipeline, so I would rather pipe the result of getProduct through a map. I would do this as follows:

    this.cartProducts.map(cartProduct => 
      this.productService
        .getProduct(cartProduct.product_name)
        .pipe(
          map((product) => {
            product.mixMatch = cartProduct.mixMatch;
            return product;
          })
        )
    )
    

    You could also use the tap function, with which you don't need to return the product.