Api service with changing arguments using Observables in Angular6

Api service with changing arguments using Observables in Angular6



The behaviour I want: when a user selects a Label from dropdown menu, api is called with that Label as an argument and a chart is redrawn using data received from api. There are multiple identical charts in the page with their respective drop down lists.
The problem is that my solution is not working and I'm not sure how to make it work. My solution:


export class ChartComponent implements OnInit, OnDestroy

private _label = new ReplaySubject<string>()
//Gets value from dropdown menu
@Input() set label(value: string) this._label.next(value)

apiSub: Subscription

constructor(private apiService: ApiService)


ngOnInit()
this.apiSub = this.apiService
.getData(this._label)
.subscribe(this.redrawGraph.bind(this),
console.error
)


ngOnDestroy()
this.apiSub.unsubscribe();


redrawGraph(data:Data)
//Chart drawing logic



export class ApiService {

response= new ReplaySubject<Observable<Data>>()

constructor(private http: HttpClient)


private static _handleError(err: HttpErrorResponse | any) 'Error: Unable to connect to API.');



getData( label: Observable<string> ): Observable<Data>
label.subscribe(label =>
this.response.next(this.http
.get<Data>(`$Urls.DATA?label=$label`)
.catch(ApiService._handleError));
)

return this.response.mergeMap(x => x)



Now redrawGraph() is only called the first time label changes. And there's obviously bad behaviour when several graphs are present, because service is a singleton as far as I know, but I don't know how else to return response without binding it to "this".



What I'm trying to avoid is having to subscribe/unsubscribe to api method from Chart component every time label changes and instead just have one stream: label changes -> api call -> chart redrawn. So how to do it properly?





the initial action should be trigger by select option even. Your code is not structured correctly. selectEvent -> pick up label -> pass to api call
– Fan Cheung
Aug 21 at 9:32





@FanCheung Are you saying, that it's bad that I'm creating ReplaySubject from input variable?
– Emilijus
Aug 21 at 9:52




1 Answer
1



To make it work you need create individual subject for each chart.
The code will looks like this:


getData( label: Observable<string> ): Observable<Data>
let response : Subject = Subject<Data>();
label.subscribe(label =>
response.next(this.http
.get<Data>(`$Urls.DATA?label=$label`)
.catch(ApiService._handleError));
)

return response;





But this.response refers to class field, so response defined here doesn't get used
– Emilijus
Aug 21 at 9:49





In my example the response is created in getData function. As I uindestood you need several responses for several charst. With one instance of response it will not work for several instances.
– alexey28
Aug 21 at 16:04





I mean "let response" and later "this.response" are two different variables (because of scope), so "return response" just returns that empty "Subject<Data>()
– Emilijus
Aug 23 at 7:49





Agree, I have fix the issue
– alexey28
Aug 23 at 8:19






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

Edmonton

Crossroads (UK TV series)