diff --git a/src/components-examples/cdk/tree/cdk-tree-nested-children-accessor/cdk-tree-nested-children-accessor-example.css b/src/components-examples/cdk/tree/cdk-tree-nested-children-accessor/cdk-tree-nested-children-accessor-example.css new file mode 100644 index 000000000000..988fa23745aa --- /dev/null +++ b/src/components-examples/cdk/tree/cdk-tree-nested-children-accessor/cdk-tree-nested-children-accessor-example.css @@ -0,0 +1,18 @@ +.example-tree-invisible { + display: none; +} + +.example-tree ul, +.example-tree li { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} +.example-tree-node { + display: block; + line-height: 40px; +} + +.example-tree-node .example-tree-node { + padding-left: 40px; +} diff --git a/src/components-examples/cdk/tree/cdk-tree-nested-children-accessor/cdk-tree-nested-children-accessor-example.html b/src/components-examples/cdk/tree/cdk-tree-nested-children-accessor/cdk-tree-nested-children-accessor-example.html new file mode 100644 index 000000000000..b100abfcf813 --- /dev/null +++ b/src/components-examples/cdk/tree/cdk-tree-nested-children-accessor/cdk-tree-nested-children-accessor-example.html @@ -0,0 +1,25 @@ + + + + + + {{node.name}} + + + + + {{node.name}} +
+ +
+
+
diff --git a/src/components-examples/cdk/tree/cdk-tree-nested-children-accessor/cdk-tree-nested-children-accessor-example.ts b/src/components-examples/cdk/tree/cdk-tree-nested-children-accessor/cdk-tree-nested-children-accessor-example.ts new file mode 100644 index 000000000000..1263ac27008b --- /dev/null +++ b/src/components-examples/cdk/tree/cdk-tree-nested-children-accessor/cdk-tree-nested-children-accessor-example.ts @@ -0,0 +1,53 @@ +import {ArrayDataSource} from '@angular/cdk/collections'; +import {CdkTree, CdkTreeModule} from '@angular/cdk/tree'; +import {Component, ViewChild} from '@angular/core'; +import {MatButtonModule} from '@angular/material/button'; +import {MatIconModule} from '@angular/material/icon'; +import {NestedFoodNode, NESTED_DATA} from '../tree-data'; + +function flattenNodes(nodes: NestedFoodNode[]): NestedFoodNode[] { + const flattenedNodes = []; + for (const node of nodes) { + flattenedNodes.push(node); + if (node.children) { + flattenedNodes.push(...flattenNodes(node.children)); + } + } + return flattenedNodes; +} + +/** + * @title Tree with nested nodes, using childAccessor + */ +@Component({ + selector: 'cdk-tree-nested-children-accessor-example', + templateUrl: 'cdk-tree-nested-children-accessor-example.html', + styleUrls: ['cdk-tree-nested-children-accessor-example.css'], + standalone: true, + imports: [CdkTreeModule, MatButtonModule, MatIconModule], +}) +export class CdkTreeNestedChildrenAccessorExample { + @ViewChild(CdkTree) tree: CdkTree; + + childrenAccessor = (dataNode: NestedFoodNode) => dataNode.children ?? []; + + dataSource = new ArrayDataSource(NESTED_DATA); + + hasChild = (_: number, node: NestedFoodNode) => !!node.children && node.children.length > 0; + + getParentNode(node: NestedFoodNode) { + for (const parent of flattenNodes(NESTED_DATA)) { + if (parent.children?.includes(node)) { + return parent; + } + } + + return null; + } + + shouldRender(node: NestedFoodNode): boolean { + // This node should render if it is a root node or if all of its ancestors are expanded. + const parent = this.getParentNode(node); + return !parent || (!!this.tree?.isExpanded(parent) && this.shouldRender(parent)); + } +} diff --git a/src/components-examples/cdk/tree/index.ts b/src/components-examples/cdk/tree/index.ts index f4f931a4c8f6..d5fa0c4d1b48 100644 --- a/src/components-examples/cdk/tree/index.ts +++ b/src/components-examples/cdk/tree/index.ts @@ -2,5 +2,6 @@ export {CdkTreeFlatChildrenAccessorExample} from './cdk-tree-flat-children-acces export {CdkTreeFlatLevelAccessorExample} from './cdk-tree-flat-level-accessor/cdk-tree-flat-level-accessor-example'; export {CdkTreeFlatExample} from './cdk-tree-flat/cdk-tree-flat-example'; export {CdkTreeNestedLevelAccessorExample} from './cdk-tree-nested-level-accessor/cdk-tree-nested-level-accessor-example'; +export {CdkTreeNestedChildrenAccessorExample} from './cdk-tree-nested-children-accessor/cdk-tree-nested-children-accessor-example'; export {CdkTreeNestedExample} from './cdk-tree-nested/cdk-tree-nested-example'; export {CdkTreeComplexExample} from './cdk-tree-complex/cdk-tree-complex-example'; diff --git a/src/dev-app/tree/tree-demo.html b/src/dev-app/tree/tree-demo.html index 2e2b98e87f39..d3b846ceaa0a 100644 --- a/src/dev-app/tree/tree-demo.html +++ b/src/dev-app/tree/tree-demo.html @@ -27,6 +27,10 @@ CDK Nested tree (levelAccessor) + + CDK Nested tree (childrenAccessor) + + Dynamic flat tree diff --git a/src/dev-app/tree/tree-demo.ts b/src/dev-app/tree/tree-demo.ts index c1b875b24390..40e0e5c02b40 100644 --- a/src/dev-app/tree/tree-demo.ts +++ b/src/dev-app/tree/tree-demo.ts @@ -13,6 +13,7 @@ import { CdkTreeNestedExample, CdkTreeFlatLevelAccessorExample, CdkTreeNestedLevelAccessorExample, + CdkTreeNestedChildrenAccessorExample, CdkTreeFlatChildrenAccessorExample, CdkTreeComplexExample, } from '@angular/components-examples/cdk/tree'; @@ -44,6 +45,7 @@ import {MatTreeModule} from '@angular/material/tree'; CdkTreeNestedExample, CdkTreeFlatChildrenAccessorExample, CdkTreeFlatLevelAccessorExample, + CdkTreeNestedChildrenAccessorExample, CdkTreeNestedLevelAccessorExample, CdkTreeComplexExample, CommonModule,