I have two sibling components each one communicates and send data through Behaviorsubject which is in service. Component A is subscribe inside ngOnInit for data coming from component B.
Component B Listen for message coming from websoket , when the message arrives I`m triggering method which updates the Behaviorsubject value.So when the new date arrives from component B , component A must shown confirmation modal but the modal is not showning because angular change detection is not being triggered even if I use Object.assign().
Where am I wrong ?
Here is my code:
product.service.ts
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class ProductService {
subjectProps: any = {
showErrorModal: undefined,
showSuccessfullyModal: undefined,
};
_subject$ = new BehaviorSubject(this.subjectProps);
event = this._subject$.asObservable();
constructor() { }
updateSubjectProps(data: any) {
this._subject$.next(data);
};
}
successfully-modal.component.ts
import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
import { Subscription } from 'rxjs';
import { ProductService } from '../../../services/product-catalogue.service';
@Component({
selector: 'successfully-modal',
templateUrl: './successfully-modal.component.html',
styleUrls: ['./successfully-modal.component.scss']
})
export class ImportCompletedSuccessfullyModalComponent implements OnInit, OnDestroy {
showErrorModal: boolean = false;
showSuccessfullyModal: boolean = false;
productSubscription: Subscription
constructor(private productService: ProductService) { }
ngOnInit(): void {
this.productSubscription = this.productService.event.subscribe(data => {
if (data) {
// Here I need to open successflully confirmation modal
this.showSuccessfullyModal = data.showSuccessfullyModal;
}
});
}
ngOnDestroy(): void {
if (this.productSubscription) {
this.productSubscription.unsubscribe();
}
}
}
products.component.ts
import { Component, OnDestroy, OnInit } from '@angular/core';
import { ProductService } from './services/product-catalogue.service';
import { Subscription } from 'rxjs';
import { webSocketListener } from '../../../event-bus';
@Component({
selector: 'products',
templateUrl: './products.component.html',
styleUrls: ['./products.component.scss']
})
export class MigrationToolComponent implements OnInit, OnDestroy {
subjectProps: any;
productSubscription: Subscription
isLoading: boolean;
products: any[] = [];
constructor(private productService: ProductService) { }
ngOnInit(): void {
this.fetchProducts();
this.productSubscription = this.productService.event.subscribe(data => {
this.subjectProps = data;
});
webSocketListener.on((message: any) => {
this.checkProductStatus(message);
});
}
fetchProducts(): void {
this.isLoading = true;
this.productService.getProducts().subscribe(res => {
this.isLoading = false;
this.products = res.products;
}),
error => {
this.isLoading = false;
console.log(error);
}
}
checkProductStatus(message: string) {
let subjectProps = Object.assign({}, this.subjectProps);
if (message === 'failed') {
subjectProps.showErrorModal = true;
subjectProps.showSuccessfullyModal = false;
}
if (message === 'success') {
subjectProps.showSuccessfullyModal = true;
subjectProps.showErrorModal = false;
}
this.productService.updateSubjectProps(subjectProps);
this.fetchProducts();
}
ngOnDestroy(): void {
if (this.productSubscription) {
this.productSubscription.unsubscribe();
}
}
}
This is related to the webSocketListener (probably) works outside of angular. You should call checkProductStatus function in angular, you can use NgZone service this.
import { Component, OnDestroy, OnInit, NgZone } from '@angular/core';
import { ProductService } from './services/product-catalogue.service';
import { Subscription } from 'rxjs';
import { webSocketListener } from '../../../event-bus';
@Component({
selector: 'products',
templateUrl: './products.component.html',
styleUrls: ['./products.component.scss'],
})
export class MigrationToolComponent implements OnInit, OnDestroy {
constructor(private productService: ProductService, private ngZone: NgZone) {}
ngOnInit(): void {
webSocketListener.on((message: any) => {
this.ngZone.run(() => {
this.checkProductStatus(message);
});
});
}
}