6

I have a chart component that loads data from http:

export class BarChartComponent implements OnInit {
    dataObservable: Observable<any>;
    
    constructor(private httpClient: HttpClient){
         this.dataObservable =  this.httpClient.get<any[]>(response.dataEndpoint);
    }
    
    ngOnInit() {
        this.dataObservable.subscribe((data: any) => {
            //draw chart
        })
    }
    
    search() {
        this.dataObservable = this.httpClient.get<any[]>(`${this.dataEndpoint}/category=123`);
        
        this.dataObservable.subscribe((data: any) => {
            //draw chart
        })
    }
}

I set the dataObservable in constructor and subscribed in ngOnInit() function. But I changed the URL using a querystring and get a request again. So I subscribed again to new. But I have subscribed in ngOnInit().

Can I reload observable without subscribing again?

1
  • 1
    Observables aren't able to do that, but you could use a Subject for that. Commented Mar 6, 2020 at 8:18

3 Answers 3

5

Everything that needs to be changed over time can be pushed into a subject. With this in mind the following solution should fit your needs:

export class BarChartComponent implements OnInit {
  url$: Subject<string> = new Subject();
  
  dataObservable$: Observable<any> = url$.pipe(
    switchMap(url => this.httpClient.get<any[]>(url))
  );
  
  search(url) {
    this.url$.next(url);
  }
  
  ngOnInit() {
    this.dataSubscription = this.dataObservable.subscribe((data: any) => {
      //draw chart
    })
  }
  
  ngOnDestroy() {
    this.dataSubscription.unsubscribe();
  }
}

Whenever the url$ changes you push it to the subject. Then you reach the inner httpClient get function via the switchMap. This will request with the new URL and respond to your dataObservable$

Sign up to request clarification or add additional context in comments.

2 Comments

Don't you mean everything that needs to be changed over time can be pushed into a Subject?
Subject, BehaviorSubject, ReplaySubject - all extend Observable. But I adjust it for reading purpose.
0

You may use async pipe.

Assign the http call result to a subject variable in component.

export class BarChartComponent implements OnInit {
    dataObservable: Subject<any>;

    constructor(private httpClient: HttpClient){}

    ngOnInit() {
        this.dataObservable =  this.httpClient.get<any[]>(GET_URL);
    }

    search() {
        this.dataObservable = this.httpClient.get<any[]>(GET_URL);
    }
}

Then subscription can be handled in html file as below:

<div *ngFor="let item of dataObservable | async">
    // code here
</div>

Or

<ng-container *ngIf="dataObservable | async as items">
    // result can be accessed by items
</ng-container>

You may read further here or here.

1 Comment

This will cause page scroll to most top, when you have long list of the iterable items. This happens due to View re-render itself when you subscribe to same observable
-1

If you have any observable which is not finalized you should always unsubscribe from it.

export class BarChartComponent implements OnInit, OnDestroy {
    dataObservable: Observable<any>;
    dataSubscription: Subscription;

    constructor(private httpClient: HttpClient){
         this.dataObservable =  this.httpClient.get<any[]>(response.dataEndpoint);
    }

    ngOnInit() {
        this.dataSubscription = this.dataObservable.subscribe((data: any) => {
            //draw chart
        })
    }

    ngOnDestroy() {
        this.dataSubscription.unsubscribe();
    }

    ...

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.