Skip to content

Commit

Permalink
fix(cdk/tree): expandAll not expanding all nodes (#30226)
Browse files Browse the repository at this point in the history
Fixes that the tree wasn't recursing down and expanding all child nodes when calling `expandAll`.

Fixes #29865.
  • Loading branch information
crisbeto authored Dec 27, 2024
1 parent a6a70f6 commit 0f053ff
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 19 deletions.
30 changes: 26 additions & 4 deletions src/cdk/tree/tree.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1481,6 +1481,32 @@ describe('CdkTree', () => {
.withContext(`expect an expanded node`)
.toBe(1);
});

it('should expand/collapse all nested nodes when calling expandAll/collapseAll', () => {
configureCdkTreeTestingModule([IsExpandableOrderingTest]);
const fixture = TestBed.createComponent(IsExpandableOrderingTest);
const component = fixture.componentInstance;
const data = fixture.componentInstance.dataSource;
treeElement = fixture.nativeElement.querySelector('cdk-tree');

data[0].children[0].children.push(new MinimalTestData('extra'));
data[0].children[0].children[0].children.push(new MinimalTestData('extra'));
fixture.detectChanges();

component.tree.expandAll();
fixture.detectChanges();
expect(getNodes(treeElement).map(n => n.getAttribute('aria-expanded'))).toEqual([
'true',
'true',
'true',
'true',
]);

component.tree.collapseAll();
fixture.detectChanges();

expect(getNodes(treeElement).map(n => n.getAttribute('aria-expanded'))).toEqual(['false']);
});
});

export class TestData {
Expand Down Expand Up @@ -1698,10 +1724,6 @@ class SimpleCdkTreeApp {

@ViewChild(CdkTree) tree: CdkTree<TestData>;
@ViewChildren(CdkTreeNodePadding) paddingNodes: QueryList<CdkTreeNodePadding<TestData>>;

expandAll() {
this.tree.expandAll();
}
}

@Component({
Expand Down
40 changes: 25 additions & 15 deletions src/cdk/tree/tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -716,10 +716,7 @@ export class CdkTree<T, K = T>
if (this.treeControl) {
this.treeControl.expandAll();
} else if (this._expansionModel) {
const expansionModel = this._expansionModel;
expansionModel.select(
...this._flattenedNodes.value.map(child => this._getExpansionKey(child)),
);
this._forEachExpansionKey(keys => this._expansionModel?.select(...keys));
}
}

Expand All @@ -728,10 +725,7 @@ export class CdkTree<T, K = T>
if (this.treeControl) {
this.treeControl.collapseAll();
} else if (this._expansionModel) {
const expansionModel = this._expansionModel;
expansionModel.deselect(
...this._flattenedNodes.value.map(child => this._getExpansionKey(child)),
);
this._forEachExpansionKey(keys => this._expansionModel?.deselect(...keys));
}
}

Expand Down Expand Up @@ -776,13 +770,7 @@ export class CdkTree<T, K = T>
if (!expanded) {
return [];
}
return this._findChildrenByLevel(
levelAccessor,
flattenedNodes,

dataNode,
1,
);
return this._findChildrenByLevel(levelAccessor, flattenedNodes, dataNode, 1);
}),
);
}
Expand Down Expand Up @@ -1153,6 +1141,28 @@ export class CdkTree<T, K = T>
this._ariaSets.set(parentKey, group);
}
}

/** Invokes a callback with all node expansion keys. */
private _forEachExpansionKey(callback: (keys: K[]) => void) {
const toToggle: K[] = [];
const observables: Observable<T[]>[] = [];

this._nodes.value.forEach(node => {
toToggle.push(this._getExpansionKey(node.data));
observables.push(this._getDescendants(node.data));
});

if (observables.length > 0) {
combineLatest(observables)
.pipe(take(1), takeUntil(this._onDestroy))
.subscribe(results => {
results.forEach(inner => inner.forEach(r => toToggle.push(this._getExpansionKey(r))));
callback(toToggle);
});
} else {
callback(toToggle);
}
}
}

/**
Expand Down

0 comments on commit 0f053ff

Please sign in to comment.