I have a tree of nodes, each time user "expands" a node, an http request is invoked to get it's children.
I'm looking for an RXJS pipeline to recursively expand all tree nodes and emit the expanded tree.
( StackBlitz demo )
The way I do it now, is to mutate the source and output the mutated object when done. Is there a way for me to simplify this hell ? possibly without mutating source .
// 'ROOT' nodes
const rootNodes = [{ id: 0, parent: true }, { id: 1000, parent: true }];
// map the root nodes to a recursive function that mutate node and returns its children observables
const getChildrenOfRoot$ = rootNodes.map(node => getChildren(node));
// call the observables, in parallels, when done, print the *** mutated *** source.
forkJoin(...getChildrenOfRoot$).subscribe(() => console.log(rootNodes));
function getChildren(node: Node): Observable<Node[]> {
return getChildrenFromServer(node.id).pipe(
// if no children returned, don't continue
filter((children: Node[]) => !!(children?.length)),
// mutate argument's .children property with the returned children array.
tap((children: Node[]) => (node.children = children)),
mergeMap((children: Node[]) => {
// mape children to observables returning either their children, or, an empty array, based on 'parent' property.
const getChildrenOfChildren$ = children.map(c => (c.parent ? getChildren(c) : of([])));
return forkJoin(...getChildrenOfChildren$);
})
);
}
