ProductGalleryComponent.html iterates over products. The click event of each image calls the setSelectedProduct function passing to it the product that was clicked.
<div class="row py-3 px-2" style="background: #f5f6f8">
<div
class="col d-flex flex-column col-12 col-md-4 col-lg-3 mb-4 gallery-img-col"
*ngFor="let product of products"
>
<img
class="gallery-img"
src="assets/img/{{ product.images[0] }}"
(click)="setSelectedProduct(product)"
/>
</div>
</div>
The setSelectedProduct function of ProductGalleryComponent.ts calls the setSelectedPRoduct function of the ProductGalleryService, passing the selected product. It then navigates to the SelectedProductComponent.
public setSelectedProduct = (product: ProductModel) => {
this.productGalleryService.setSelectedProduct(product);
this.router.navigateByUrl('/selected-product');
}
ProductGalleryService declares a subject and an observable of the subject. In the setSelecedProduct function, it calls the next function of the subject, passing to it the selected product:
export class ProductGalleryService {
public selectedProductSubject = new Subject<ProductModel>();
selectedProductSubject$ = this.selectedProductSubject.asObservable();
public setSelectedProduct = (product: ProductModel) => {
this.selectedProductSubject.next(product);
}
}
The SelectedProductComponent subscribes to the selectedProductSubject of ProductGalleryService via the constructor. It is expected to receive the product broadcast by ProductGalleryService.selectedProductSubject but the product is never received.
export class SelectedProductComponent {
private productGalleryService = inject(ProductGalleryService)
constructor() {
this.setSelectedProduct()
}
private setSelectedProduct = () => {
this.productGalleryService.selectedProductSubject$.subscribe((product) => {
this.selectedProduct = product;
console.log('selectedProductSubject.selectedProduct', this.selectedProduct)
})
}
}
I believe the ProductGalleryService.selectedProductSubject$ subject has already emitted before the SelectedProductComponent subscribes.
How to get around this problem?
RxJS offers another type of Subject - a ReplaySubject. When subscribing to a ReplaySubject, it will re-emit any previously pushed values. The ReplaySubject has a buffer size, how many items to store and re-emit. For your use case, I believe you only care about the last one, so BufferSize is 1.
public selectedProductSubject = new ReplaySubject<ProductModel>(1);