3

I am using Angular 5 and have the following problem:

I have a route which contains a parameter year. The related component should now display the data for that year which is retrieved by a service. When first routing to such an URL, this works fine. If I change the parameter year, the component is not reloaded (as expected), just OnInit() is called again. In this method, I try to reload the data by calling the service method with the new year, but it does not work. Here is my code:

test.component.ts:

public ngOnInit() {
    this.route.paramMap.subscribe( params => {
        if (params.has('year')) {
            this.loadData(params.get('year'));
        } else {
            this.loadData();
        }
    });
}

public loadData(year?: string): void {
    this.testService.getData(year).subscribe(data => {
        // edit and set to variables
    });
}

test.service.ts:

public getData(year) {
    return Observable.forkJoin(
        this.getPart1(year),
        this.getPart2(year)
    );
}

private getPart1(year): Observable<CustomObject[]> {
    let url = this.baseUrl;
    if (year) url = url.concat("?year=" + year);
    return this.http.get<CustomObject[]>(url, httpOptions).pipe(
        catchError(this.handleError<CustomObject[]>())
    )
}

private getPart2(year): Observable<OtherCustomObject[]> {
    let url = this.baseUrl + '/path';
    if (year) url = url.concat("?year=" + year);
    return this.http.get<OtherCustomObject[]>(url, httpOptions).pipe(
        catchError(this.handleError<OtherCustomObject[]>())
    )
}

How to force the Observable to reload the HTTP request? I tried using a (Replay)Subject instead of Observables, but that didn't work.

Any help is highly appreciated :)

1 Answer 1

3

You can use a BehaviorSubject for that with switchMap:

//First of all, create your reloader subject
reloader$ = new BehaviorSubject(null);

//Then connect it to your observable
public getData(year) {
    return this.reloader$.switchMap(() => Observable.forkJoin(
        this.getPart1(year),
        this.getPart2(year)
    ));
}

Because this is a BehaviorSubject, the first call will work like a charm as it will give null as first value.

Then, you can create a basic reload() method:

public reload(){
  this.reloader$.next(null);
}

Because this will make reloader$ observable emit a new value, the rest of the observable chain will be triggered again, making new requests to reload your data.

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

3 Comments

Correct me if Im wrong, but in this case switchMapTo would be better suited. And I see no reasong to use a BehaviorSubject. A normal subject would be enough.
@Jota.Toledo Using a BehaviorSubject is mandatory here, else you won't receive anything until you call reload() for the first time, as the previous observable of the chain (the reloader) will have 0 value available.
Dont think that the use of the behavior subject is mandatory in any way. That problem could easily be solved by calling the reload method on ngOnInit or similar to trigger a first fetch of data.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.