Material Tree

Material tree

Overview
Mat-tree được thiết kế theo material design style sử dụng để hiển thị dữ liệu phân cấp

Có hai loại tree
- Flat tree
- Nested tree
 Cấu trúc DOM sẽ khác tùy thuộc vào loại tree.
Flat tree
Trong một flat tree, hệ thống phân cấp được làm phẳng; các node không được thiết kế lồng bên trong nhau, mà thay vào đó được viết dưới dạng anh chị em theo trình tự. Sử dụng thuộc tính TreeFlattener  sử dụng để tạo danh sách phẳng các phần từ dữ liệu phân cấp. "Level" của mỗi node tree được đọc thông qua phương thức getLevel của TreeControl; level này có thể được sử dụng để định kiểu node sao cho nó được hiện thị theo cấp thích hợp.
<mat-tree>
  <mat-tree-node> parent node </mat-tree-node>
  <mat-tree-node> -- child node1 </mat-tree-node>
  <mat-tree-node> -- child node2 </mat-tree-node>
</mat-tree>
Flat trees are generally easier to style and inspect.

Nested tree
Trong Nested tree, các node con được đặt bên trong node cha của chúng trong DOM.

<mat-tree>
   <mat-nested-tree-node>
     parent node
     <mat-nested-tree-node> -- child node1 </mat-nested-tree-node>
     <mat-nested-tree-node> -- child node2 </mat-nested-tree-node>
   </mat-nested-tree-node>
</mat-tree>
tree lồng nhau dễ làm việc hơn khi các mối quan hệ phân cấp được thể hiện trực quan hơn thì khó thực hiện với các node phẳng.
Features
Bản thân <mat-tree> chỉ liên quan đến kết xuất cấu trúc tree. Các tính năng bổ sung có thể được xây dựng trên ngọn tree bằng cách thêm hành vi bên trong các mẫu node (ví dụ: padding và toogle). Các tương tác ảnh hưởng đến dữ liệu được kết xuất (như mở rộng / thu gọn) nên được truyền qua nguồn dữ liệu của bảng.

 TreeControl
TreeControl kiểm soát trạng thái mở rộng / thu gọn của các node tree. Người dùng có thể mở rộng / thu gọn một node tree theo cách đệ quy thông qua điều khiển tree. Đối với node tree lồng nhau, hàm getChildren cần chuyển đến NestedTreeControl để làm cho nó hoạt động đệ quy. Hàm getChildren có thể trả về một con có thể quan sát được cho một node đã cho hoặc một mảng con. Đối với node tree flat, các hàm getLevel và isExpandable cần chuyển đến FlatTreeControl để làm cho nó hoạt động đệ quy.

 Toogle
Một matTreeNodeToggle có thể được thêm vào trong mẫu node tree để mở rộng / thu gọn node tree. Chuyển đổi bật tắt các chức năng mở rộng / thu gọn trong TreeControl và có thể mở rộng / thu gọn một node tree theo cách đệ quy bằng cách đặt [matTreeNodeToggleRecursive] thành true.

Chuyển đổi có thể được đặt ở bất cứ đâu trong node tree và chỉ được bật bằng hành động nhấp chuột.

 Padding(Chỉ flat tree)
MatTreeNodePadding có thể được đặt trong mẫu node của tree phẳng để hiển thị thông tin mức của node tree phẳng.

Nested tree không cần phần padding này vì phần padding có thể dễ dàng thêm vào cấu trúc phân cấp trong DOM.

 Accessibility
Tree không có văn bản hoặc nhãn nên được cung cấp một nhãn có ý nghĩa thông qua nhãn aria hoặc aria-labellingby. Mặc định chỉ đọc aria thành true nếu nó không được đặt.

Tree’s role là tree. Các node cha được cho role = "group", trong khi các node lá được cho vai trò = "treeitem"

mat-tree không tự quản lý bất kỳ tương tác focus hoặc bàn phím. Người dùng có thể thêm các tương tác focus hoặc bàn phím mong muốn trong app của họ.

In action
>ng g c mat-tree
Ở file mat-tree-component.html sửa lại nội dung thành
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<mat-tree [dataSource]="dataSource" [treeControl]="treeControl">
<!-- This is the tree node template for leaf nodes -->
<mat-tree-node *matTreeNodeDef="let node" matTreeNodePadding>
<!-- use a disabled button to provide padding for tree leaf -->
<button mat-icon-button disabled></button>
{{node.name}}
</mat-tree-node>
<!-- This is the tree node template for expandable nodes -->
<mat-tree-node *matTreeNodeDef="let node;when: hasChild" matTreeNodePadding>
<button mat-icon-button matTreeNodeToggle
[attr.aria-label]="'toggle ' + node.name">
<mat-icon class="mat-icon-rtl-mirror">
{{treeControl.isExpanded(node) ? 'expand_more' : 'chevron_right'}}
</mat-icon>
</button>
{{node.name}}
</mat-tree-node>
</mat-tree>
Ở file mat-tree-component.ts sửa lại nội dung thành
import { Component, OnInit } from '@angular/core';
import { FlatTreeControl } from '@angular/cdk/tree';
import { MatTreeFlattener, MatTreeFlatDataSource } from '@angular/material';
interface FoodNode {
name: string;
children?: FoodNode[];
}

const TREE_DATA: FoodNode[] = [
{
name: 'Fruit',
children: [
{name: 'Apple'},
{name: 'Banana'},
{name: 'Fruit loops'},
]
}, {
name: 'Vegetables',
children: [
{
name: 'Green',
children: [
{name: 'Broccoli'},
{name: 'Brussel sprouts'},
]
}, {
name: 'Orange',
children: [
{name: 'Pumpkins'},
{name: 'Carrots'},
]
},
]
},
];

/** Flat node with expandable and level information */
interface ExampleFlatNode {
expandable: boolean;
name: string;
level: number;
}

@Component({
selector: 'app-mat-tree',
templateUrl: './mat-tree.component.html',
styleUrls: ['./mat-tree.component.css']
})
export class MatTreeComponent implements OnInit {

private transformer = (node: FoodNode, level: number) => {
return {
expandable: !!node.children && node.children.length > 0,
name: node.name,
level: level,
};
}

treeControl = new FlatTreeControl<ExampleFlatNode>(
node => node.level, node => node.expandable);

treeFlattener = new MatTreeFlattener(
this.transformer, node => node.level, node => node.expandable, node => node.children);

dataSource = new MatTreeFlatDataSource(this.treeControl, this.treeFlattener);

constructor() {
this.dataSource.data = TREE_DATA;
}

hasChild = (_: number, node: ExampleFlatNode) => node.expandable;
ngOnInit() {
}

}

Kết quả chạy thử nghiệm 

Refference

Nhận xét

Bài đăng phổ biến từ blog này

.Net secure coding guidelines

Tìm hiểm Checkbox Angular Material