Reputation: 11
I'm working with Rxjs observable in angular component and learning things. I have scenario where i need to pass data from component to service based on some events.
Price.service.ts
export class PriceService{
private priceUpdate: BehaviorSubject<Object> = new BehaviorSubject({});
private oldPriceUpdate: BehaviorSubject<Object> = new BehaviorSubject({});
getPriceUpdate(){
return this.priceUpdate.asObservable();
}
getOldPrice(){
return this.oldPriceUpdate.asObservable();
}
}
Above service is used in component to get price update.
Price.component.ts
@Component({
selector: 'price',
templateUrl: 'price.component.html',
styleUrls: ['price.component.css']
})
export class PriceComponent{
updateIndicator: BehaviorSubject<Object> = new BehaviorSubject({});
constructor(private priceService:PriceService, private techIndicator:TechnicalIndicatorService){
this.techIndicator.subscribeUpdateIndicator(this.updateIndicator.asObservable());
this.priceService.getPriceUpdate().subscribe(
(newPrice:any) => {
this.updatePrice(newPrice);
}
)
this.priceService.getOldPriceUpdate().subscribe(
(oldPrice:any ) => {
//some business logic
this.updateIndicator.next({{data: data, ....});
});
}
private updatePrice(newPrice:any){
//.... some business logic....
this.updateIndicator.next({data: data, ....});
}
}
After getting new price from PriceService in component I have another service where I'm doing some technical studies. I need to pass data to service, for which I'm using the behaviour subject in component and Service is subscribing to it. (Different from usual approach where component is subscribing.)
Please let me know if its a valid way to use observable.
TechnicalIndicator.service.ts
export class TechnicalIndicatorService{
subscribeUpdateIndicator(updateIndicator:Observable<Object>){
updateIndicator.subscribe(
(obj:any) => {
// some logic
});
}
}
However the subscription is working only once in the TechnicalIndicatorService. For any data update afterwards, its is not triggering the subscription. Please let me know what I'm missing here.
Upvotes: 1
Views: 3431
Reputation: 1
hello mate you should provide it in the top level module
import { Post } from './../contance/models/posts';
import { Subject } from 'rxjs';
import { Injectable } from '@angular/core';
import { USER, User } from '../contance';
import { usersState } from './states/users.state';
import { deleteFromArray, updateArray } from '../utils/array-utils';
@Injectable({
providedIn: 'root'
})
export class StoreService {
state = {
usersState,
}
private Posts = new Subject<Post[]>()
posts = this.Posts.asObservable()
constructor() {
}
getUser() {
if (localStorage.getItem(USER)) {
return JSON.parse(localStorage.getItem(USER)) as User
}
}
public postsActions = {
fetch: (posts: Post[]) => this.Posts.next(posts),
delete: (id: number) => deleteFromArray('id', id, this.Posts.observers),
edit: (object: Post) => updateArray('id', object.id, this.Posts.observers, object, true)
}
}
you need to provide service in app.module :
/**
* @license
* Copyright Akveo. All Rights Reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*/
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { NgModule } from '@angular/core';
import { CoreModule } from './@core/core.module';
import { ThemeModule } from './@theme/theme.module';
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import {
NbChatModule,
NbDatepickerModule,
NbDialogModule,
NbMenuModule,
NbSidebarModule,
NbToastrModule,
NbWindowModule,
} from '@nebular/theme';
import { HttpRequestModule } from './@core/interceptor/http-request.module';
import { StoreService } from './@core/context/store.service';
@NgModule({
declarations: [AppComponent],
imports: [
BrowserModule,
BrowserAnimationsModule,
HttpRequestModule,
AppRoutingModule,
NbSidebarModule.forRoot(),
NbMenuModule.forRoot(),
NbDatepickerModule.forRoot(),
NbDialogModule.forRoot(),
NbWindowModule.forRoot(),
NbToastrModule.forRoot(),
NbChatModule.forRoot({
messageGoogleMapKey: 'AIzaSyA_wNuCzia92MAmdLRzmqitRGvCF7wCZPY',
}),
CoreModule.forRoot(),
ThemeModule.forRoot(),
],
providers: [StoreService],
bootstrap: [AppComponent],
})
export class AppModule {
}
Upvotes: 0
Reputation: 9341
You are having too many Subjects. You can prevent them and make it simpler.
From what you wrote I understand you want to inform TechnicalIndicatorService
to do something either of priceUpdate
or oldPriceUpdate
changes.
Solution 1:
For this you dont need to come to component at all. You can just do this. Directly inject PriceService
into TechnicalIndicatorService
.
TechnicalIndicatorService:
export class TechnicalIndicatorService{
constructor(private priceService: PriceService){
priceService.getPriceUpdate().subscribe(this.doSomething);
priceService.getOldPrice().subscribe(this.doSomething);
}
private doSomething(update){
}
}
You dont need to write anything in component .
Solution 2:
But you dont want them to be aware of each other and want to do only from Component, then you can do this :
PriceComponent
export class PriceComponent{
constructor(
private priceService:PriceService,
private techIndicator:TechnicalIndicatorService
){
this.techIndicator.subscribeUpdateIndicator(
return Observable.merge(
priceService.getPriceUpdate(),
priceService.getOldPrice()
);
);
}
}
If you still want to use Subjects let me know I will check why they are failing.
Upvotes: 1