I have a scenario where in one of the components sends a value via form and i need to pass it to another component, so I have used Behavior Subject via a shared service as I thought it will be the best way to achieve what I need.
service.ts
private Type$ = new BehaviorSubject<any>(null); getType(): Observable<any> { return this.Type$.asObservable(); } emitType(type: any | null): void { this.emitType$.next(type); }
component.ts where i am emitting
``` save(){
.......
this.service.emitType(_data.Type!);
}```
component.ts where i am using
ngOninit(){ this.service.getType().subscribe((type: any)=>{ this.Type = type console.log('types', this.Type); }) }
I found out behavior subject takes in only the last value, so i used ReplaySubject, now on console.log I can see that multiple values are fetched over my screen but still at the end type has last value. I need different type values to do different stuff
CodePudding user response:
You can use pairwise()
to emit the current and previous values as an array, so when you subscribe, you'll get both:
private Type$ = new Subject<any>();
getType(): Observable<any[]> {
return this.Type$.pipe(
startWith(undefined),
pairwise(),
shareReplay(1),
);
}
emitType(type: any | null): void {
this.Type$.next(type);
}
Since pairwise()
will not emit until it receives 2 emissions, we use startWith
to feed it an initial undefined
value. To achieve the multicast and replay functionality that BehaviorSubject
has, we can add shareReply(1)
.
Then, in your component:
ngOnInit() {
this.service.getType().subscribe(
([previous, current]) => {
this.Type = ...;
console.log('types', { previous, current});
}
)
}
Note, it's not beneficial to wrap observables in functions (unless you are passing arguments needed to define it). Observables are lazy and nothing will happen until it is subscribed. Instead of creating a getType()
method and returning observable, you can simply define a property that is an observable:
private _Type$ = new Subject<any>();
public type$: Observable<any[]> = this._Type$.pipe(
startWith(undefined),
pairwise(),
shareReplay(1),
);
emitType(type: any | null): void {
this._Type$.next(type);
}
Then, in your component:
ngOnInit() {
this.service.type$.subscribe(
([previous, current]) => {
this.Type = ...;
console.log('types', { previous, current});
}
)
}
Here's a little StackBlitz you can play with.