import { Component, OnInit, Input, Output, EventEmitter, ViewChild, ElementRef, AfterViewInit, OnChanges, SimpleChanges } from '@angular/core'; import { Subscription } from 'rxjs/Subscription'; import { isNull } from './fn.utils'; import { MatTree, get } from './mat-tree'; import { MatTreeController } from './mat-tree-controller'; import { NodeCheckedEvent, NodeEvent } from './mat-tree.events'; import { MatTreeService } from './mat-tree.service'; @Component({ selector: 'mat-tree-internal', templateUrl: './mat-tree-internal.component.html', }) export class MatTreeInternalComponent implements OnInit, AfterViewInit, OnChanges { public controller: MatTreeController; @Input() tree: MatTree; @Input() direction: string; // first element or the directive matching the selector @ViewChild('checkbox') public checkboxElementRef: ElementRef; private subscriptions: Subscription[] = []; constructor(public treeService: MatTreeService) { } public ngOnChanges(changes: SimpleChanges): void { this.controller = new MatTreeController(this); } onSwitchFoldingType() { this.tree.switchFoldingType(); this.treeService.fireNodeSwitchFoldingType(this.tree); } switchNodeCheckStatus() { this.treeService.isCheckboxClicked = true; if (!this.tree.checked) { this.onNodeChecked(); } else { this.onNodeUnchecked(); } } public onNodeChecked(): void { if (!this.checkboxElementRef) { return; } this.checkboxElementRef.nativeElement.indeterminate = false; // 发送事件, 所有节点都会收到 this.treeService.fireNodeChecked(this.tree); // 操作子节点 this.executeOnChildController(controller => controller.check()); this.tree.checked = true; } public onNodeUnchecked(): void { if (!this.checkboxElementRef) { return; } this.checkboxElementRef.nativeElement.indeterminate = false; this.treeService.fireNodeUnchecked(this.tree); this.executeOnChildController(controller => controller.uncheck()); this.tree.checked = false; } public ngAfterViewInit(): void { // if (this.tree.checked && !(this.tree as any).firstCheckedFired) { // (this.tree as any).firstCheckedFired = true; // this.treeService.fireNodeChecked(this.tree); // } } public ngOnInit(): void { const nodeId = get(this.tree, 'node.id', ''); if (nodeId) { this.controller = new MatTreeController(this); this.treeService.setController(nodeId, this.controller); this.treeService.setLeaf(this.tree); } // this.settings = this.settings || new Ng2TreeSettings(); // this.isReadOnly = !get(this.settings, 'enableCheckboxes', true); // if (this.tree.isRoot() && this.settings.rootIsVisible === false) { // this.tree.disableCollapseOnInit(); // } this.subscriptions.push( this.treeService.nodeChecked$ .merge(this.treeService.nodeUnchecked$) .filter((e: NodeCheckedEvent) => this.eventContainsId(e) && this.tree.hasChild(e.node)) .subscribe((e: NodeCheckedEvent) => this.updateCheckboxState()) ); this.subscriptions.push( this.treeService.move$.subscribe((e: NodeEvent) => { this.switchNodeCheckStatus(); console.log('move'); }) ); } // 更新父节点 updateCheckboxState(): void { // Calling setTimeout so the value of isChecked will be updated and after that I'll check the children status. setTimeout(() => { const checkedChildrenAmount = this.tree.checkedChildrenAmount(); if (!this.checkboxElementRef) { console.warn('checkbox is required'); return; } if (checkedChildrenAmount === 0) { // 顶节点 this.checkboxElementRef.nativeElement.indeterminate = false; this.tree.checked = false; this.treeService.fireNodeUnchecked(this.tree); } else if (checkedChildrenAmount === this.tree.loadedChildrenAmount()) { this.checkboxElementRef.nativeElement.indeterminate = false; this.tree.checked = true; this.treeService.fireNodeChecked(this.tree); } else { this.tree.checked = false; this.checkboxElementRef.nativeElement.indeterminate = true; this.treeService.fireNodeIndetermined(this.tree); } }); } /** * 遍历子节点 * @param executor {function} */ private executeOnChildController(executor: (controller: MatTreeController) => void) { // 子节点 if (this.tree.hasLoadedChildern()) { this.tree.children.forEach((child: MatTree) => { const controllers = this.treeService.getController(child.id); // controllers 包含了左右两颗树 controllers.forEach(controller => { if (!isNull(controller)) { executor(controller); } }); }); // 是不是通过点击checkbox触发 } else if (this.treeService.isCheckboxClicked === true) { this.treeService.isCheckboxClicked = false; const currentController = this.treeService.getController(this.tree.id); currentController.forEach(controller => executor(controller)); } } private eventContainsId(event: NodeEvent): boolean { if (!event.node.id) { console.warn( '"Node with checkbox" feature requires a unique id assigned to every node, please consider to add it.' ); return false; } return true; } }