I have two interfaces:
interface Project {
...
CurrentProjectPhase : number
...
}
and
interface Phase {
PhaseId : number
Projects$ : Observable<Project[]>
...
}
both are returned from individual http services as oberservables.
I'm trying to sort the projects via their currentPhase attribute into the phases. Before I did this via subscribing to both and attaching a filtered subset of all project elements to the phase:
this.phaseService.loadAllPhases().subscribe((ph) => {
this.projectService.loadAllProjects().subscribe((pj) => {
ph.forEach((p : Phase) => {
p.Projects = pj.filter(project => project.CurrentProjectPhase === p.Id);
});
this.phases = ph;
this.projects = pj;
})
})
In that case the Phase had a Projects: Project[] instead of the Observable.
I would like to refactor this to stay as observables as long as possible. I've tried this:
this.projects$ = this.projectService.getProjects();
this.phases$ = this.phaseService.getPhases().pipe(
tap(phases => phases.map(phase=>
phase.Projects$ = this.projects$?.pipe(
map(projects=> projects.filter(project => project.CurrentProjectPhase == phase.Id)))
))
)
But (ofcourse) it doesn't work. Any suggestions?
CodePudding user response:
You could combine them:
const filtered = this.projectService.getProjects().pipe(
combineLatestWith(this.phaseService.getPhases()),
map(([projects, phases]) => {
phases.forEach((phase) => {
phase.projects = projects.filter(project => project.CurrentProjectPhase == phase.Id)
});
return phases;
}),
)
Or something like that. My brain's a bit tired, so this might be a tad off.
Now you can subscribe to filtered
to get the results whenever you need them.
CodePudding user response:
I would try to use a forkJoin if you are using HTTP calls that will both complete once it is returned. I am not sure why you would like to keep Projects as an observable in the Phases interface but maybe the code below will work:
const projects$ = this.projectService.getProjects();
const phases$ = this.phaseService.getPhases();
const combined$: Observable<Phase[]> = forkJoin([projects$, phases$]).pipe(
map(([projects, phases]) => {
return phases.map(phase => {
const phaseProjects = projects.filter(project => project.CurrentProjectPhase === phase.PhaseId);
return {...phase, Projects$: of(phaseProjects)};
})
})
);