Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/cdk/tree/toggle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,17 @@ export class CdkTreeNodeToggle<T, K = T> {

constructor(protected _tree: CdkTree<T, K>, protected _treeNode: CdkTreeNode<T, K>) {}

// Toggle the expanded or collapsed state of this node.
//
// Focus this node with expanding or collapsing it. This ensures that the active node will always
// be visible when expanding and collapsing.
_toggle(event: Event): void {
this.recursive
? this._tree.toggleDescendants(this._treeNode.data)
: this._tree.toggle(this._treeNode.data);

this._tree._keyManager.focusItem(this._treeNode);

event.stopPropagation();
}

Expand Down
39 changes: 36 additions & 3 deletions src/cdk/tree/tree-redesign.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,28 @@ describe('CdkTree redesign', () => {
.toBe(0);
});

it('should focus a node when collapsing it', () => {
// Create a tree with two nodes. A parent node and its child.
dataSource.clear();
const parent = dataSource.addData();
dataSource.addChild(parent);

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

// focus the child node
getNodes(treeElement)[1].click();
fixture.detectChanges();

// collapse the parent node
getNodes(treeElement)[0].click();
fixture.detectChanges();

expect(getNodes(treeElement).map(x => x.getAttribute('tabindex')))
.withContext(`Expecting parent node to be focused since it was collapsed.`)
.toEqual(['0', '-1']);
});

it('should expand/collapse the node recursively', () => {
expect(dataSource.data.length).toBe(3);

Expand Down Expand Up @@ -1312,22 +1334,33 @@ class FakeDataSource extends DataSource<TestData> {
return child;
}

addData(level: number = 1) {
addData(level: number = 1): TestData {
const nextIndex = ++this.dataIndex;

let copiedData = this.data.slice();
copiedData.push(
new TestData(`topping_${nextIndex}`, `cheese_${nextIndex}`, `base_${nextIndex}`, level),
const newData = new TestData(
`topping_${nextIndex}`,
`cheese_${nextIndex}`,
`base_${nextIndex}`,
level,
);
copiedData.push(newData);

this.data = copiedData;

return newData;
}

getRecursiveData(nodes: TestData[] = this._dataChange.getValue()): TestData[] {
return [
...new Set(nodes.flatMap(parent => [parent, ...this.getRecursiveData(parent.children)])),
];
}

clear() {
this.data = [];
this.dataIndex = 0;
}
}

function getNodes(treeElement: Element): HTMLElement[] {
Expand Down