I am new to Angular and Observables. I have a service that receives a URL I want to pass to my observable and render data every time a new URL is passed to it with NgFor. Any ex
I think I understand your problem.
The http.get(url) is a single-use observable. It's not a stream that can be triggered multiple times like subjects can. You will need to create your own subject and use that as a proxy.
export class ClientService {
constructor(private http: HttpClient) {
}
private eventPublisher: Subject<Event[]> = new Subject<Event[]>();
receiveEvent(eventId){
// call http client here, and publish results to event publisher
const eventUrl = eventId;
this.http.get<Event[]>(eventUrl).subscribe(response => {
this.eventPublisher.next(response);
});
}
renderEvent(eventUrl): Observable<Event[]>{
// do not subscribe to http client here, subscribe to event publisher
return this.eventPublisher.asObservable();
}
This is the pub-sub design pattern (publisher - subscriber). It might be useful to read up on other solutions to this design pattern using Angular, as this is a fairly trivial example.
Edit:
You will also want to unsubscribe in your component once you're done with the subscription to avoid memory leaks.
Something like this is a simple pattern:
export class MyComponent implements OnInit, OnDestroy() {
constructor(private myService: MyService) { }
private destroyed: Subject<void> = new Subject<void>();
ngOnInit(): void {
this.myService.myMethod().pipe(
takeUntil(() => this.destroyed)
).subscribe(() => {
// do stuff
});
}
ngOnDestroy(): void {
this.destroyed.next(undefined);
this.destroyed.complete();
}
}
Although it does get repetitive if you need to start doing it a lot. I personally use this method: https://stackoverflow.com/a/45709120/5367916
// This sample using angular 9/10
// Component name: list.component.ts
import { HttpClient } from '@angular/common/http';
import { Component, OnInit } from '@angular/core';
import { NgZone} from '@angular/core';
import {HttpServiceService} from './../http-service.service';
@Component({
selector: 'app-list',
templateUrl: './list.component.html',
styleUrls: ['./list.component.scss']
})
export class ListComponent implements OnInit {
constructor(
private http: HttpServiceService,
private zone: NgZone
) { }
brews: object;
ngOnInit(): void {
this.http.getPeople().subscribe(data => {
this.brews = data;
alert(JSON.stringify(this.brews));
console.log(this.brews);
});
}
}
//--------------------------------
// This is my http service
// Component Name: http-service.service.ts
import { Observable, of } from 'rxjs';
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class HttpServiceService {
constructor() { }
getPeople(): Observable<any>{
const myNameArray = [{
firstName: 'Algem',
lastName: 'Mojedo',
age: 63
}];
return of(myNameArray);
}
}
//--------------------------
// should display in alert
localhost:4200 says
[{"firstName":"Algem","lastName":"Mojedo","age":"60"}]
Happy coding..