diff --git a/src/cdk/tree/tree-with-tree-control.spec.ts b/src/cdk/tree/tree-with-tree-control.spec.ts index 23b3bd9d38db..2566da86d598 100644 --- a/src/cdk/tree/tree-with-tree-control.spec.ts +++ b/src/cdk/tree/tree-with-tree-control.spec.ts @@ -19,6 +19,7 @@ import { import {CollectionViewer, DataSource} from '@angular/cdk/collections'; import {Directionality, Direction} from '@angular/cdk/bidi'; +import {createKeyboardEvent} from '@angular/cdk/testing/testbed/fake-events'; import {combineLatest, BehaviorSubject, Observable} from 'rxjs'; import {map} from 'rxjs/operators'; @@ -27,6 +28,7 @@ import {FlatTreeControl} from './control/flat-tree-control'; import {NestedTreeControl} from './control/nested-tree-control'; import {CdkTreeModule, CdkTreeNodePadding} from './index'; import {CdkTree, CdkTreeNode} from './tree'; +import {LEFT_ARROW, RIGHT_ARROW} from '../keycodes'; describe('CdkTree', () => { /** Represents an indent for expectNestedTreeToMatch */ @@ -758,7 +760,7 @@ describe('CdkTree', () => { it('with the right aria-expanded attrs', () => { expect(getNodeAttributes(getNodes(treeElement), 'aria-expanded')) .withContext('aria-expanded attributes') - .toEqual([null, null, null]); + .toEqual(['false', 'false', 'false']); component.toggleRecursively = false; let data = dataSource.data; @@ -773,10 +775,10 @@ describe('CdkTree', () => { // in DOM unless the parent node is expanded. expect(getNodeAttributes(getNodes(treeElement), 'aria-expanded')) .withContext('aria-expanded attributes') - .toEqual([null, 'true', 'false', null]); + .toEqual(['false', 'true', 'false', 'false']); }); - it('should expand/collapse the node multiple times', () => { + it('should expand/collapse the node multiple times using keyboard', () => { component.toggleRecursively = false; let data = dataSource.data; const child = dataSource.addChild(data[1], false); @@ -793,7 +795,10 @@ describe('CdkTree', () => { fixture.detectChanges(); - (getNodes(treeElement)[1] as HTMLElement).click(); + let node = getNodes(treeElement)[1] as HTMLElement; + + node.focus(); + node.dispatchEvent(createKeyboardEvent('keydown', RIGHT_ARROW)); fixture.detectChanges(); expect(component.treeControl.expansionModel.selected.length) @@ -807,7 +812,9 @@ describe('CdkTree', () => { [`topping_3 - cheese_3 + base_3`], ); - (getNodes(treeElement)[1] as HTMLElement).click(); + node = getNodes(treeElement)[1] as HTMLElement; + node.focus(); + node.dispatchEvent(createKeyboardEvent('keydown', LEFT_ARROW)); fixture.detectChanges(); expectNestedTreeToMatch( @@ -820,7 +827,9 @@ describe('CdkTree', () => { .withContext(`Expect node collapsed`) .toBe(0); - (getNodes(treeElement)[1] as HTMLElement).click(); + node = getNodes(treeElement)[1] as HTMLElement; + node.focus(); + node.dispatchEvent(createKeyboardEvent('keydown', RIGHT_ARROW)); fixture.detectChanges(); expect(component.treeControl.expansionModel.selected.length) @@ -1585,9 +1594,9 @@ class NestedCdkTreeAppWithToggle { getChildren = (node: TestData) => node.observableChildren; - treeControl: TreeControl = new NestedTreeControl(this.getChildren, { - isExpandable: node => node.children.length > 0, - }); + isExpandable?: (node: TestData) => boolean; + + treeControl: TreeControl = new NestedTreeControl(this.getChildren); dataSource: FakeDataSource | null = new FakeDataSource(this.treeControl); @ViewChild(CdkTree) tree: CdkTree; diff --git a/src/cdk/tree/tree.ts b/src/cdk/tree/tree.ts index ac82bc83c5f2..a4f638e80214 100644 --- a/src/cdk/tree/tree.ts +++ b/src/cdk/tree/tree.ts @@ -1175,8 +1175,14 @@ export class CdkTreeNode implements OnDestroy, OnInit, TreeKeyManagerI /** Determines if the tree node is expandable. */ _isExpandable(): boolean { - if (typeof this._tree.treeControl?.isExpandable === 'function') { - return this._tree.treeControl.isExpandable(this._data); + if (this._tree.treeControl) { + if (typeof this._tree.treeControl?.isExpandable === 'function') { + return this._tree.treeControl.isExpandable(this._data); + } + + // For compatibility with trees created using TreeControl before we added + // CdkTreeNode#isExpandable. + return true; } return this._inputIsExpandable; } @@ -1260,18 +1266,16 @@ export class CdkTreeNode implements OnDestroy, OnInit, TreeKeyManagerI /** Collapses this data node. Implemented for TreeKeyManagerItem. */ collapse(): void { - if (!this._isExpandable()) { - return; + if (this.isExpandable) { + this._tree.collapse(this._data); } - this._tree.collapse(this._data); } /** Expands this data node. Implemented for TreeKeyManagerItem. */ expand(): void { - if (!this._isExpandable()) { - return; + if (this.isExpandable) { + this._tree.expand(this._data); } - this._tree.expand(this._data); } _setTabFocusable() { diff --git a/src/components-examples/material/tree/tree-nested-overview/tree-nested-overview-example.html b/src/components-examples/material/tree/tree-nested-overview/tree-nested-overview-example.html index 0be398dd2701..8f9e8036bd13 100644 --- a/src/components-examples/material/tree/tree-nested-overview/tree-nested-overview-example.html +++ b/src/components-examples/material/tree/tree-nested-overview/tree-nested-overview-example.html @@ -8,8 +8,7 @@ + matTreeNodeToggle>