Skip to content

Commit 9be93a3

Browse files
committed
docs(tree): add tree examples
1 parent e288bc2 commit 9be93a3

File tree

12 files changed

+342
-2
lines changed

12 files changed

+342
-2
lines changed

src/material-examples/material-module.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,13 @@ import {
1010
MatSlideToggleModule, MatSnackBarModule, MatTableModule, MatTabsModule, MatToolbarModule,
1111
MatTooltipModule, MatFormFieldModule, MatExpansionModule, MatStepperModule
1212
} from '@angular/material';
13+
import {MatTreeModule} from '@angular/material-experimental/tree';
14+
import {CdkTreeModule} from '@angular/cdk-experimental/tree';
1315

1416
@NgModule({
1517
exports: [
1618
CdkTableModule,
19+
CdkTreeModule,
1720
MatAutocompleteModule,
1821
MatButtonModule,
1922
MatButtonToggleModule,
@@ -45,6 +48,7 @@ import {
4548
MatTabsModule,
4649
MatToolbarModule,
4750
MatTooltipModule,
51+
MatTreeModule
4852
]
4953
})
5054
export class ExampleMaterialModule {}

src/material-examples/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,11 @@
2424
"homepage": "https://github.com/angular/material2#readme",
2525
"peerDependencies": {
2626
"@angular/cdk": "0.0.0-PLACEHOLDER",
27+
"@angular/cdk-experimental": "0.0.0-PLACEHOLDER",
2728
"@angular/core": "0.0.0-NG",
2829
"@angular/common": "0.0.0-NG",
2930
"@angular/material": "0.0.0-PLACEHOLDER",
31+
"@angular/material-experimental": "0.0.0-PLACEHOLDER",
3032
"@angular/material-moment-adapter": "0.0.0-PLACEHOLDER"
3133
},
3234
"dependencies": {
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.tree-demo-invisible {
2+
display: none;
3+
}
4+
5+
ul, li {
6+
-webkit-margin-before: 0;
7+
-webkit-margin-after: 0;
8+
list-style-type: none;
9+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<mat-tree [dataSource]="dataSource" [treeControl]="treeControl">
2+
<mat-tree-node *matTreeNodeDef="let node" matTreeNodeToggle matTreeNodePadding>
3+
{{node.key}} : {{node.value}}
4+
</mat-tree-node>
5+
6+
<mat-tree-node *matTreeNodeDef="let node;when: hasChild" matTreeNodePadding>
7+
<button mat-icon-button matTreeNodeToggle
8+
[attr.aria-label]="'toggle ' + node.key">
9+
<mat-icon>
10+
{{treeControl.isExpanded(node) ? 'expand_more' : 'chevron_right'}}
11+
</mat-icon>
12+
</button>
13+
{{node.key}} : {{node.value}}
14+
</mat-tree-node>
15+
</mat-tree>
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
import {Component, Injectable} from '@angular/core';
2+
import {FlatTreeControl} from '@angular/cdk-experimental/tree';
3+
import {MatTreeFlattener, MatTreeFlatDataSource} from '@angular/material-experimental/tree';
4+
import {of} from 'rxjs/observable/of';
5+
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
6+
7+
export class JsonNode {
8+
children: JsonNode[];
9+
key: string;
10+
value: any;
11+
}
12+
13+
/** Flat node with expandable and level information */
14+
export class JsonFlatNode {
15+
key: string;
16+
value: any;
17+
level: number;
18+
expandable: boolean;
19+
}
20+
21+
const TREE_DATA = `{"Tina":
22+
{
23+
"Documents": {
24+
"angular": {
25+
"src": {
26+
"core": "ts",
27+
"compiler": "ts"
28+
}
29+
},
30+
"material2": {
31+
"src": {
32+
"button": "ts",
33+
"checkbox": "ts",
34+
"input": "ts"
35+
}
36+
}
37+
},
38+
"Downloads": {
39+
"Tutorial": "html",
40+
"November": "pdf",
41+
"October": "pdf"
42+
},
43+
"Pictures": {
44+
"Sun": "png",
45+
"Woods": "jpg",
46+
"Photo Booth Library": {
47+
"Contents": "dir",
48+
"Pictures": "dir"
49+
}
50+
},
51+
"Applications": {
52+
"Chrome": "app",
53+
"Calendar": "app",
54+
"Webstorm": "app"
55+
}
56+
}}`;
57+
58+
@Injectable()
59+
export class JsonDatabase {
60+
dataChange: BehaviorSubject<JsonNode[]> = new BehaviorSubject<JsonNode[]>([]);
61+
62+
get data(): JsonNode[] { return this.dataChange.value; }
63+
64+
constructor() {
65+
this.initialize();
66+
}
67+
68+
initialize() {
69+
const dataObject = JSON.parse(TREE_DATA);
70+
const data = this.buildJsonTree(dataObject, 0);
71+
this.dataChange.next(data);
72+
}
73+
74+
buildJsonTree(value: any, level: number) {
75+
let data: any[] = [];
76+
for (let k in value) {
77+
let v = value[k];
78+
let node = new JsonNode();
79+
node.key = `${k}`;
80+
if (v === null || v === undefined) {
81+
// no action
82+
} else if (typeof v === 'object') {
83+
node.children = this.buildJsonTree(v, level + 1);
84+
} else {
85+
node.value = v;
86+
}
87+
data.push(node);
88+
}
89+
return data;
90+
}
91+
}
92+
93+
/**
94+
* @title Tree with flat nodes
95+
*/
96+
@Component({
97+
selector: 'tree-flat-overview-example',
98+
templateUrl: 'tree-flat-overview-example.html',
99+
styleUrls: ['tree-flat-overview-example.css'],
100+
providers: [JsonDatabase]
101+
})
102+
export class TreeFlatOverviewExample {
103+
104+
treeControl: FlatTreeControl<JsonFlatNode>;
105+
106+
treeFlattener: MatTreeFlattener<JsonNode, JsonFlatNode>;
107+
108+
dataSource: MatTreeFlatDataSource<JsonNode, JsonFlatNode>;
109+
110+
constructor(database: JsonDatabase) {
111+
this.treeFlattener = new MatTreeFlattener(this.transformer, this._getLevel,
112+
this._isExpandable, this._getChildren);
113+
this.treeControl = new FlatTreeControl<JsonFlatNode>(this._getLevel, this._isExpandable);
114+
this.dataSource = new MatTreeFlatDataSource(this.treeControl, this.treeFlattener);
115+
116+
database.dataChange.subscribe(data => {
117+
this.dataSource.data = data;
118+
})
119+
}
120+
121+
transformer = (node: JsonNode, level: number) => {
122+
let flatNode = new JsonFlatNode();
123+
flatNode.key = node.key;
124+
flatNode.value = node.value;
125+
flatNode.level = level;
126+
flatNode.expandable = !!node.children;
127+
return flatNode;
128+
};
129+
130+
private _getLevel = (node: JsonFlatNode) => { return node.level; };
131+
132+
private _isExpandable = (node: JsonFlatNode) => { return node.expandable; };
133+
134+
private _getChildren = (node: JsonNode) => { return of(node.children); };
135+
136+
hasChild = (_: number, _nodeData: JsonFlatNode) => { return _nodeData.expandable; };
137+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.tree-demo-invisible {
2+
display: none;
3+
}
4+
5+
ul, li {
6+
-webkit-margin-before: 0;
7+
-webkit-margin-after: 0;
8+
list-style-type: none;
9+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<mat-tree [dataSource]="nestedDataSource" [treeControl]="nestedTreeControl">
2+
<mat-tree-node *matTreeNodeDef="let node" matTreeNodeToggle>
3+
<li>
4+
<div>{{node.key}}: {{node.value}}</div>
5+
</li>
6+
</mat-tree-node>
7+
8+
<mat-nested-tree-node *matTreeNodeDef="let node; when: hasNestedChild">
9+
<li>
10+
<div class="mat-tree-node">
11+
<button mat-icon-button matTreeNodeToggle
12+
[attr.aria-label]="'toggle ' + node.key">
13+
<mat-icon>
14+
{{nestedTreeControl.isExpanded(node) ? 'expand_more' : 'chevron_right'}}
15+
</mat-icon>
16+
</button>
17+
{{node.key}}
18+
</div>
19+
<ul [class]="nestedTreeControl.isExpanded(node) ? '' : 'tree-demo-invisible'">
20+
<ng-container matTreeNodeOutlet></ng-container>
21+
</ul>
22+
</li>
23+
</mat-nested-tree-node>
24+
</mat-tree>
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import {Component, Injectable} from '@angular/core';
2+
import {NestedTreeControl} from '@angular/cdk-experimental/tree';
3+
import {MatTreeNestedDataSource} from '@angular/material-experimental/tree';
4+
import {of} from 'rxjs/observable/of';
5+
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
6+
7+
export class JsonNode {
8+
children: JsonNode[];
9+
key: string;
10+
value: any;
11+
}
12+
13+
const TREE_DATA = `{"Tina":
14+
{
15+
"Documents": {
16+
"angular": {
17+
"src": {
18+
"core": "ts",
19+
"compiler": "ts"
20+
}
21+
},
22+
"material2": {
23+
"src": {
24+
"button": "ts",
25+
"checkbox": "ts",
26+
"input": "ts"
27+
}
28+
}
29+
},
30+
"Downloads": {
31+
"Tutorial": "html",
32+
"November": "pdf",
33+
"October": "pdf"
34+
},
35+
"Pictures": {
36+
"Sun": "png",
37+
"Woods": "jpg",
38+
"Photo Booth Library": {
39+
"Contents": "dir",
40+
"Pictures": "dir"
41+
}
42+
},
43+
"Applications": {
44+
"Chrome": "app",
45+
"Calendar": "app",
46+
"Webstorm": "app"
47+
}
48+
}}`;
49+
50+
@Injectable()
51+
export class JsonDatabase {
52+
dataChange: BehaviorSubject<JsonNode[]> = new BehaviorSubject<JsonNode[]>([]);
53+
54+
get data(): JsonNode[] { return this.dataChange.value; }
55+
56+
constructor() {
57+
this.initialize();
58+
}
59+
60+
initialize() {
61+
const dataObject = JSON.parse(TREE_DATA);
62+
const data = this.buildJsonTree(dataObject, 0);
63+
this.dataChange.next(data);
64+
}
65+
66+
buildJsonTree(value: any, level: number) {
67+
let data: any[] = [];
68+
for (let k in value) {
69+
let v = value[k];
70+
let node = new JsonNode();
71+
node.key = `${k}`;
72+
if (v === null || v === undefined) {
73+
// no action
74+
} else if (typeof v === 'object') {
75+
node.children = this.buildJsonTree(v, level + 1);
76+
} else {
77+
node.value = v;
78+
}
79+
data.push(node);
80+
}
81+
return data;
82+
}
83+
}
84+
85+
/**
86+
* @title Tree with nested nodes
87+
*/
88+
@Component({
89+
selector: 'tree-nested-overview-example',
90+
templateUrl: 'tree-nested-overview-example.html',
91+
styleUrls: ['tree-nested-overview-example.css'],
92+
providers: [JsonDatabase]
93+
})
94+
export class TreeNestedOverviewExample {
95+
nestedTreeControl: NestedTreeControl<JsonNode>;
96+
97+
nestedDataSource: MatTreeNestedDataSource<JsonNode>;
98+
99+
constructor(database: JsonDatabase) {
100+
this.nestedTreeControl = new NestedTreeControl<JsonNode>(this._getChildren);
101+
this.nestedDataSource = new MatTreeNestedDataSource();
102+
103+
database.dataChange.subscribe(data => {
104+
this.nestedDataSource.data = data;
105+
})
106+
}
107+
108+
private _getChildren = (node: JsonNode) => { return of(node.children); };
109+
110+
111+
hasNestedChild = (_: number, nodeData: JsonNode) => {return !(nodeData.value); };
112+
}

src/material-examples/tsconfig-build.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,10 @@
2424
"paths": {
2525
"@angular/material/*": ["../../dist/packages/material/*"],
2626
"@angular/material": ["../../dist/packages/material/public-api"],
27+
"@angular/material-experimental/*": ["../../dist/packages/material-experimental/*"],
2728
"@angular/material-moment-adapter": ["../../dist/packages/material-moment-adapter"],
28-
"@angular/cdk/*": ["../../dist/packages/cdk/*"]
29+
"@angular/cdk/*": ["../../dist/packages/cdk/*"],
30+
"@angular/cdk-experimental/*": ["../../dist/packages/cdk-experimental/*"]
2931
}
3032
},
3133
"files": [

src/material-examples/tsconfig.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
"@angular/cdk/*": ["../cdk/*"],
1111
"@angular/material/*": ["../lib/*"],
1212
"@angular/material": ["../lib/public-api.ts"],
13-
"@angular/material-moment-adapter": ["../material-moment-adapter/public-api.ts"]
13+
"@angular/material-moment-adapter": ["../material-moment-adapter/public-api.ts"],
14+
"@angular/cdk-experimental/*": ["../cdk-experimental/*"],
15+
"@angular/material-experimental/*": ["../materila-experimental/*"]
1416
}
1517
},
1618
"include": ["./**/*.ts"]

src/material-experimental/tree/tree.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ used to style the node such that it is indented to the appropriate level.
2424
</mat-tree>
2525
```
2626

27+
<!-- example(tree-flat-overview) -->
28+
2729
Flat trees are generally easier to style and inspect. They are also more friendly to
2830
scrolling variations, such as infinite or virtual scrolling
2931

@@ -43,6 +45,8 @@ outlet to keep all the children nodes.
4345
</mat-tree>
4446
```
4547

48+
<!-- example(tree-nested-overview) -->
49+
4650
Nested trees are easier to work with when hierarchical relationships are visually
4751
represented in ways that would be difficult to accomplish with flat nodes.
4852

0 commit comments

Comments
 (0)