From d2359adce7980a0bb6a154b6cea9c55b31883e2e Mon Sep 17 00:00:00 2001 From: Yuan Gao Date: Wed, 14 Mar 2018 10:43:32 -0700 Subject: [PATCH] docs(tree): add cdk tree examples to material-example --- src/cdk/tree/tree.md | 5 + .../cdk-tree-flat/cdk-tree-flat-example.css | 4 + .../cdk-tree-flat/cdk-tree-flat-example.html | 12 ++ .../cdk-tree-flat/cdk-tree-flat-example.ts | 162 ++++++++++++++++++ .../cdk-tree-nested-example.css | 15 ++ .../cdk-tree-nested-example.html | 15 ++ .../cdk-tree-nested-example.ts | 132 ++++++++++++++ .../tree-flat-overview-example.css | 6 - .../tree-flat-overview-example.html | 3 +- .../tree-flat-overview-example.ts | 6 +- .../tree-nested-overview-example.css | 4 +- .../tree-nested-overview-example.html | 5 +- .../tree-nested-overview-example.ts | 6 +- 13 files changed, 358 insertions(+), 17 deletions(-) create mode 100644 src/material-examples/cdk-tree-flat/cdk-tree-flat-example.css create mode 100644 src/material-examples/cdk-tree-flat/cdk-tree-flat-example.html create mode 100644 src/material-examples/cdk-tree-flat/cdk-tree-flat-example.ts create mode 100644 src/material-examples/cdk-tree-nested/cdk-tree-nested-example.css create mode 100644 src/material-examples/cdk-tree-nested/cdk-tree-nested-example.html create mode 100644 src/material-examples/cdk-tree-nested/cdk-tree-nested-example.ts diff --git a/src/cdk/tree/tree.md b/src/cdk/tree/tree.md index 62835fac659d..3651dcfc5f7e 100644 --- a/src/cdk/tree/tree.md +++ b/src/cdk/tree/tree.md @@ -7,6 +7,9 @@ these two types of trees. #### Flat tree + + + In a flat tree, the hierarchy is flattened; nodes are not rendered inside of each other, but instead are rendered as siblings in sequence. An instance of `TreeFlattener` is used to generate the flat list of items from hierarchical data. The "level" of each tree node is read through the `getLevel` @@ -28,6 +31,8 @@ variations, such as infinite or virtual scrolling. #### Nested tree + + In nested tree, children nodes are placed inside their parent node in DOM. The parent node contains a node outlet into which children are projected. diff --git a/src/material-examples/cdk-tree-flat/cdk-tree-flat-example.css b/src/material-examples/cdk-tree-flat/cdk-tree-flat-example.css new file mode 100644 index 000000000000..775f480239de --- /dev/null +++ b/src/material-examples/cdk-tree-flat/cdk-tree-flat-example.css @@ -0,0 +1,4 @@ +.demo-tree-node { + display: flex; + align-items: center; +} diff --git a/src/material-examples/cdk-tree-flat/cdk-tree-flat-example.html b/src/material-examples/cdk-tree-flat/cdk-tree-flat-example.html new file mode 100644 index 000000000000..efab0bfec51c --- /dev/null +++ b/src/material-examples/cdk-tree-flat/cdk-tree-flat-example.html @@ -0,0 +1,12 @@ + + + + {{node.filename}}: {{node.type}} + + + + {{node.filename}}: {{node.type}} + + diff --git a/src/material-examples/cdk-tree-flat/cdk-tree-flat-example.ts b/src/material-examples/cdk-tree-flat/cdk-tree-flat-example.ts new file mode 100644 index 000000000000..a2361760d279 --- /dev/null +++ b/src/material-examples/cdk-tree-flat/cdk-tree-flat-example.ts @@ -0,0 +1,162 @@ +import {Component, Injectable} from '@angular/core'; +import {FlatTreeControl} from '@angular/cdk/tree'; +import {MatTreeFlattener, MatTreeFlatDataSource} from '@angular/material/tree'; +import {of} from 'rxjs/observable/of'; +import {Observable} from 'rxjs/Observable'; +import {BehaviorSubject} from 'rxjs/BehaviorSubject'; + +/** + * File node data with nested structure. + * Each node has a filename, and a type or a list of children. + */ +export class FileNode { + children: FileNode[]; + filename: string; + type: any; +} + +/** Flat node with expandable and level information */ +export class FileFlatNode { + filename: string; + type: any; + level: number; + expandable: boolean; +} + +/** + * The file structure tree data in string. The data could be parsed into a Json object + */ +const TREE_DATA = ` + { + "Documents": { + "angular": { + "src": { + "core": "ts", + "compiler": "ts" + } + }, + "material2": { + "src": { + "button": "ts", + "checkbox": "ts", + "input": "ts" + } + } + }, + "Downloads": { + "Tutorial": "html", + "November": "pdf", + "October": "pdf" + }, + "Pictures": { + "Sun": "png", + "Woods": "jpg", + "Photo Booth Library": { + "Contents": "dir", + "Pictures": "dir" + } + }, + "Applications": { + "Chrome": "app", + "Calendar": "app", + "Webstorm": "app" + } +}`; + +/** + * File database, it can build a tree structured Json object from string. + * Each node in Json object represents a file or a directory. For a file, it has filename and type. + * For a directory, it has filename and children (a list of files or directories). + * The input will be a json object string, and the output is a list of `FileNode` with nested + * structure. + */ +@Injectable() +export class FileDatabase { + dataChange: BehaviorSubject = new BehaviorSubject([]); + + get data(): FileNode[] { return this.dataChange.value; } + + constructor() { + this.initialize(); + } + + initialize() { + // Parse the string to json object. + const dataObject = JSON.parse(TREE_DATA); + + // Build the tree nodes from Json object. The result is a list of `FileNode` with nested + // file node as children. + const data = this.buildFileTree(dataObject, 0); + + // Notify the change. + this.dataChange.next(data); + } + + /** + * Build the file structure tree. The `value` is the Json object, or a sub-tree of a Json object. + * The return value is the list of `FileNode`. + */ + buildFileTree(value: any, level: number): FileNode[] { + let data: any[] = []; + for (let k in value) { + let v = value[k]; + let node = new FileNode(); + node.filename = `${k}`; + if (v === null || v === undefined) { + // no action + } else if (typeof v === 'object') { + node.children = this.buildFileTree(v, level + 1); + } else { + node.type = v; + } + data.push(node); + } + return data; + } +} + +/** + * @title Tree with flat nodes + */ +@Component({ + selector: 'cdk-tree-flat-example', + templateUrl: 'cdk-tree-flat-example.html', + styleUrls: ['cdk-tree-flat-example.css'], + providers: [FileDatabase] +}) +export class CdkTreeFlatExample { + + treeControl: FlatTreeControl; + + treeFlattener: MatTreeFlattener; + + dataSource: MatTreeFlatDataSource; + + constructor(database: FileDatabase) { + this.treeFlattener = new MatTreeFlattener(this.transformer, this._getLevel, + this._isExpandable, this._getChildren); + this.treeControl = new FlatTreeControl(this._getLevel, this._isExpandable); + this.dataSource = new MatTreeFlatDataSource(this.treeControl, this.treeFlattener); + + database.dataChange.subscribe(data => { + this.dataSource.data = data; + }); + } + + transformer = (node: FileNode, level: number) => { + let flatNode = new FileFlatNode(); + flatNode.filename = node.filename; + flatNode.type = node.type; + flatNode.level = level; + flatNode.expandable = !!node.children; + return flatNode; + } + + private _getLevel = (node: FileFlatNode) => { return node.level; }; + + private _isExpandable = (node: FileFlatNode) => { return node.expandable; }; + + private _getChildren = (node: FileNode): Observable => { return of(node.children); }; + + hasChild = (_: number, _nodeData: FileFlatNode) => { return _nodeData.expandable; }; +} diff --git a/src/material-examples/cdk-tree-nested/cdk-tree-nested-example.css b/src/material-examples/cdk-tree-nested/cdk-tree-nested-example.css new file mode 100644 index 000000000000..ca6636073bca --- /dev/null +++ b/src/material-examples/cdk-tree-nested/cdk-tree-nested-example.css @@ -0,0 +1,15 @@ +.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; + padding-left: 40px; +} diff --git a/src/material-examples/cdk-tree-nested/cdk-tree-nested-example.html b/src/material-examples/cdk-tree-nested/cdk-tree-nested-example.html new file mode 100644 index 000000000000..9a26d39b0833 --- /dev/null +++ b/src/material-examples/cdk-tree-nested/cdk-tree-nested-example.html @@ -0,0 +1,15 @@ + + + + {{node.filename}}: {{node.type}} + + + + {{node.filename}}: {{node.type}} +
+ +
+
+
diff --git a/src/material-examples/cdk-tree-nested/cdk-tree-nested-example.ts b/src/material-examples/cdk-tree-nested/cdk-tree-nested-example.ts new file mode 100644 index 000000000000..97d5392a09c2 --- /dev/null +++ b/src/material-examples/cdk-tree-nested/cdk-tree-nested-example.ts @@ -0,0 +1,132 @@ +import {Component, Injectable} from '@angular/core'; +import {NestedTreeControl} from '@angular/cdk/tree'; +import {MatTreeNestedDataSource} from '@angular/material/tree'; +import {of} from 'rxjs/observable/of'; +import {BehaviorSubject} from 'rxjs/BehaviorSubject'; + +/** + * Json node data with nested structure. Each node has a filename and a value or a list of children + */ +export class FileNode { + children: FileNode[]; + filename: string; + type: any; +} + +/** + * The Json tree data in string. The data could be parsed into Json object + */ +const TREE_DATA = ` + { + "Documents": { + "angular": { + "src": { + "core": "ts", + "compiler": "ts" + } + }, + "material2": { + "src": { + "button": "ts", + "checkbox": "ts", + "input": "ts" + } + } + }, + "Downloads": { + "Tutorial": "html", + "November": "pdf", + "October": "pdf" + }, + "Pictures": { + "Sun": "png", + "Woods": "jpg", + "Photo Booth Library": { + "Contents": "dir", + "Pictures": "dir" + } + }, + "Applications": { + "Chrome": "app", + "Calendar": "app", + "Webstorm": "app" + } + }`; + +/** + * File database, it can build a tree structured Json object from string. + * Each node in Json object represents a file or a directory. For a file, it has filename and type. + * For a directory, it has filename and children (a list of files or directories). + * The input will be a json object string, and the output is a list of `FileNode` with nested + * structure. + */ +@Injectable() +export class FileDatabase { + dataChange: BehaviorSubject = new BehaviorSubject([]); + + get data(): FileNode[] { return this.dataChange.value; } + + constructor() { + this.initialize(); + } + + initialize() { + // Parse the string to json object. + const dataObject = JSON.parse(TREE_DATA); + + // Build the tree nodes from Json object. The result is a list of `FileNode` with nested + // file node as children. + const data = this.buildFileTree(dataObject, 0); + + // Notify the change. + this.dataChange.next(data); + } + + /** + * Build the file structure tree. The `value` is the Json object, or a sub-tree of a Json object. + * The return value is the list of `FileNode`. + */ + buildFileTree(value: any, level: number): FileNode[] { + let data: any[] = []; + for (let k in value) { + let v = value[k]; + let node = new FileNode(); + node.filename = `${k}`; + if (v === null || v === undefined) { + // no action + } else if (typeof v === 'object') { + node.children = this.buildFileTree(v, level + 1); + } else { + node.type = v; + } + data.push(node); + } + return data; + } +} + +/** + * @title Tree with nested nodes + */ +@Component({ + selector: 'cdk-tree-nested-example', + templateUrl: 'cdk-tree-nested-example.html', + styleUrls: ['cdk-tree-nested-example.css'], + providers: [FileDatabase] +}) +export class CdkTreeNestedExample { + nestedTreeControl: NestedTreeControl; + + nestedDataSource: MatTreeNestedDataSource; + + constructor(database: FileDatabase) { + this.nestedTreeControl = new NestedTreeControl(this._getChildren); + this.nestedDataSource = new MatTreeNestedDataSource(); + + database.dataChange.subscribe(data => this.nestedDataSource.data = data); + } + + private _getChildren = (node: FileNode) => { return of(node.children); }; + + hasNestedChild = (_: number, nodeData: FileNode) => {return !(nodeData.type); }; +} diff --git a/src/material-examples/tree-flat-overview/tree-flat-overview-example.css b/src/material-examples/tree-flat-overview/tree-flat-overview-example.css index 138500bdf17a..e69de29bb2d1 100644 --- a/src/material-examples/tree-flat-overview/tree-flat-overview-example.css +++ b/src/material-examples/tree-flat-overview/tree-flat-overview-example.css @@ -1,6 +0,0 @@ -.example-tree ul, -.example-tree li { - -webkit-margin-before: 0; - -webkit-margin-after: 0; - list-style-type: none; -} diff --git a/src/material-examples/tree-flat-overview/tree-flat-overview-example.html b/src/material-examples/tree-flat-overview/tree-flat-overview-example.html index 0a24659edaaa..a9165cedb2ef 100644 --- a/src/material-examples/tree-flat-overview/tree-flat-overview-example.html +++ b/src/material-examples/tree-flat-overview/tree-flat-overview-example.html @@ -1,5 +1,6 @@ - + + {{node.filename}} : {{node.type}} diff --git a/src/material-examples/tree-flat-overview/tree-flat-overview-example.ts b/src/material-examples/tree-flat-overview/tree-flat-overview-example.ts index 86f86a8b2742..44db6b054244 100644 --- a/src/material-examples/tree-flat-overview/tree-flat-overview-example.ts +++ b/src/material-examples/tree-flat-overview/tree-flat-overview-example.ts @@ -26,7 +26,7 @@ export class FileFlatNode { /** * The file structure tree data in string. The data could be parsed into a Json object */ -const TREE_DATA = `{"Tina": +const TREE_DATA = ` { "Documents": { "angular": { @@ -61,7 +61,7 @@ const TREE_DATA = `{"Tina": "Calendar": "app", "Webstorm": "app" } -}}`; +}`; /** * File database, it can build a tree structured Json object from string. @@ -96,7 +96,7 @@ export class FileDatabase { * Build the file structure tree. The `value` is the Json object, or a sub-tree of a Json object. * The return value is the list of `FileNode`. */ - buildFileTree(value: any, level: number) { + buildFileTree(value: any, level: number): FileNode[] { let data: any[] = []; for (let k in value) { let v = value[k]; diff --git a/src/material-examples/tree-nested-overview/tree-nested-overview-example.css b/src/material-examples/tree-nested-overview/tree-nested-overview-example.css index 1bcbfb831ce1..3cbc799e0492 100644 --- a/src/material-examples/tree-nested-overview/tree-nested-overview-example.css +++ b/src/material-examples/tree-nested-overview/tree-nested-overview-example.css @@ -4,7 +4,7 @@ .example-tree ul, .example-tree li { - -webkit-margin-before: 0; - -webkit-margin-after: 0; + margin-top: 0; + margin-bottom: 0; list-style-type: none; } diff --git a/src/material-examples/tree-nested-overview/tree-nested-overview-example.html b/src/material-examples/tree-nested-overview/tree-nested-overview-example.html index efe21202abaf..0cf052680538 100644 --- a/src/material-examples/tree-nested-overview/tree-nested-overview-example.html +++ b/src/material-examples/tree-nested-overview/tree-nested-overview-example.html @@ -1,7 +1,8 @@ -
  • -
    {{node.filename}}: {{node.type}}
    +
  • + + {{node.filename}}: {{node.type}}
  • diff --git a/src/material-examples/tree-nested-overview/tree-nested-overview-example.ts b/src/material-examples/tree-nested-overview/tree-nested-overview-example.ts index 6a80f1d4c720..804a853a6e8e 100644 --- a/src/material-examples/tree-nested-overview/tree-nested-overview-example.ts +++ b/src/material-examples/tree-nested-overview/tree-nested-overview-example.ts @@ -16,7 +16,7 @@ export class FileNode { /** * The Json tree data in string. The data could be parsed into Json object */ -const TREE_DATA = `{"Tina": +const TREE_DATA = ` { "Documents": { "angular": { @@ -51,7 +51,7 @@ const TREE_DATA = `{"Tina": "Calendar": "app", "Webstorm": "app" } -}}`; + }`; /** * File database, it can build a tree structured Json object from string. @@ -86,7 +86,7 @@ export class FileDatabase { * Build the file structure tree. The `value` is the Json object, or a sub-tree of a Json object. * The return value is the list of `FileNode`. */ - buildFileTree(value: any, level: number) { + buildFileTree(value: any, level: number): FileNode[] { let data: any[] = []; for (let k in value) { let v = value[k];