In my project, I sometimes want to update the available options in a list when the user changes the selected value in another list. To do this, I've used valueChanges
with the pipe
operator and switchMap
like this:
this.form.controls.typeControl.valueChanges
.pipe(
switchMap((typeId: number) => {
return this.typesService.getProjectsByType(typeId);
}),
)
.subscribe((projects) => {
//...
});
Now I have the problem that I need to perform two http requests at once to update multiple lists instead of just one. When I try to add a second switchMap
, I get error TS2345: Argument of type 'OperatorFunction<number, Project[]>' is not assignable to parameter of type 'OperatorFunction<any, number>'.
Here is how I tried to do this:
this.form.controls.typeControl.valueChanges
.pipe(
switchMap((typeId: number) => {
return this.typesService.getProjectsByType(typeId);
}),
switchMap((typeId: number) => {
return this.typesService.getProgramsByType(typeId);
}),
)
.subscribe(([projects, programs]) => {
//...
});
How can I add a second http request here so I can process the data received by both request in the subscribe
?
CodePudding user response:
You could use combineLataest
or forkJoin
to create an observable that emits when either of it's sources emit:
this.form.controls.typeControl.valueChanges.pipe(
switchMap(typeId => combineLatest([
this.typesService.getProjectsByType(typeId),
this.typesService.getProgramsByType(typeId)
]))
)
.subscribe(([projects, programs]) => {
// ...
});
However, if these two piece of data (projectList and programList) aren't related to each other, you may find it more convenient to define them as separate observables:
private typeId$ = this.form.controls.typeControl.valueChanges;
projectList$ = this.typeId$.pipe(switchMap(id => this.typesService.getProjectsByType(id)));
programList$ = this.typeId$.pipe(switchMap(id => this.typesService.getProgramsByType(id)));
This can give you more granular control and allow you to use the async
pipe in your template a little easier:
<h1> Projects </h1>
<ul>
<li *ngFor="let project of projectList$ | async">
{{ project.name }}
</li>
</ul>
<h1> Programs </h1>
<ul>
<li *ngFor="let program of programList$ | async">
{{ program.name }}
</li>
</ul>
CodePudding user response:
forkJoin operator could help here, you can do it like this:
this.form.controls.typeControl.valueChanges
.pipe(
switchMap((typeId: number) => {
return forkJoin([
this.typesService.getProjectsByType(typeId),
this.typesService.getProgramsByType(typeId)
])
})
)
.subscribe(([projects, programs]) => {
//...
});