Let's say I have a Student with two properties: courseIds, courses.
export interface IStudent {
courseIds: number[];
courses: ICourse[];
}
export interface ICourse {
name: string;
}
When the page loads I issue a GET request to retrieve a Student where only the courseIds are populated. Then I want to validate these Id's and make an unknown number of aditional GET requests to a diferent endpoint to retrieve his Courses.
In the end I want to have a Student object with populated Courses array.
I got this far:
httpClient.get<IStudent>(url)
.pipe(
map(student => {
const validIds = [];
student.courseIds.forEach(id => {
if (isValid(id)) {
validIds.push(id);
}
}
return validIds;
}),
???
).subscribe(
???
);
Question marks indicate where I'm stuck. How can I implement this using Observables?
In your pipe you can map
and filter your valid id's before using switchMap
and forkJoin
to get an array of ICourse back.
httpClient.get<IStudent>(url)
.pipe(
map(student => student.courseIds.filter((id: number) => isValid(id))),
switchMap((ids: number[]) => forkJoin(ids.map(id => httpClient.get<ICourse>(id))))
)
.subscribe({
next: (data: ICourse[]) => {
/* use your course array */
console.log(data)
},
error: (error) => console.log(error),
}
);
You would probably want to split the http service classes up so you have clean 'gets' and do the stitching in a component service class. Then you just need to subscribe or use the async pipe in the component.