diff --git a/components/tree-select/nz-tree-select.component.ts b/components/tree-select/nz-tree-select.component.ts index 5961a5b5581..e1d43f4a125 100644 --- a/components/tree-select/nz-tree-select.component.ts +++ b/components/tree-select/nz-tree-select.component.ts @@ -250,7 +250,7 @@ export class NzTreeSelectComponent implements ControlValueAccessor, OnInit, OnDe if (this.selectedNodes.length) { const removeNode = this.selectedNodes[ this.selectedNodes.length - 1 ]; this.removeSelected(removeNode); - this.nzTreeService.$statusChange.next({ + this.nzTreeService.triggerEventChange$.next({ 'eventName': 'removeSelect', 'node' : removeNode }); diff --git a/components/tree/demo/basic.ts b/components/tree/demo/basic.ts index 1704fbbd4d1..64548acf234 100644 --- a/components/tree/demo/basic.ts +++ b/components/tree/demo/basic.ts @@ -7,21 +7,22 @@ import { NzFormatEmitEvent, NzTreeNodeOptions } from 'ng-zorro-antd'; + (nzCheckBoxChange)="nzCheck($event)" + (nzExpandChange)="nzCheck($event)"> ` }) export class NzDemoTreeBasicComponent implements OnInit { @ViewChild('treeCom') treeCom; - defaultCheckedKeys = [ '1001', '1002' ]; - defaultSelectedKeys = [ '10010', '10020' ]; + defaultCheckedKeys = [ '10020' ]; + defaultSelectedKeys = [ '10010' ]; defaultExpandedKeys = [ '100', '1001' ]; nodes: NzTreeNodeOptions[] = [ { @@ -33,7 +34,7 @@ export class NzDemoTreeBasicComponent implements OnInit { disabled: true, children: [ { title: 'leaf 1-0-0', key: '10010', disableCheckbox: true, isLeaf: true }, - { title: 'leaf 1-0-1', key: '10011', isLeaf: true, checked: true } + { title: 'leaf 1-0-1', key: '10011', isLeaf: true } ] }, { title : 'parent 1-1', @@ -50,7 +51,7 @@ export class NzDemoTreeBasicComponent implements OnInit { } nzCheck(event: NzFormatEmitEvent): void { - console.log(event, event.checkedKeys, event.keys, event.nodes); + console.log(event); } // nzSelectedKeys change diff --git a/components/tree/demo/directory.ts b/components/tree/demo/directory.ts index a86871ea984..efa7631ad6c 100644 --- a/components/tree/demo/directory.ts +++ b/components/tree/demo/directory.ts @@ -102,14 +102,13 @@ export class NzDemoTreeDirectoryComponent { openFolder(data: NzTreeNode | NzFormatEmitEvent): void { // do something if u want if (data instanceof NzTreeNode) { - data.setExpanded(!data.isExpanded); + data.isExpanded = !data.isExpanded; } else { - data.node.setExpanded(!data.node.isExpanded); + data.node.isExpanded = !data.node.isExpanded; } } activeNode(data: NzFormatEmitEvent): void { - data.node.setExpanded(true); this.activedNode = data.node; } diff --git a/components/tree/demo/draggable.ts b/components/tree/demo/draggable.ts index 70cd6bdd9b0..58ee1cae961 100644 --- a/components/tree/demo/draggable.ts +++ b/components/tree/demo/draggable.ts @@ -1,11 +1,13 @@ import { Component, OnInit } from '@angular/core'; +import { NzFormatEmitEvent } from 'ng-zorro-antd'; @Component({ selector: 'nz-demo-tree-draggable', template: ` + nzDraggable="true" + (nzOnDrop)="afterDrop($event)"> `, styles : [ ` @@ -67,6 +69,10 @@ export class NzDemoTreeDraggableComponent implements OnInit { isLeaf: true } ]; + afterDrop(event: NzFormatEmitEvent): void { + console.log(event); + } + ngOnInit(): void { } } diff --git a/components/tree/doc/index.en-US.md b/components/tree/doc/index.en-US.md index 1432f28c7ca..f33bf3ccb20 100644 --- a/components/tree/doc/index.en-US.md +++ b/components/tree/doc/index.en-US.md @@ -110,7 +110,6 @@ Almost anything can be represented in a tree structure. Examples include directo | isDisableCheckbox | Whether treeNode's checkbox can not be clicked | `boolean` | `true` / `false` | | isSelectable | Set whether the treeNode can be selected | `boolean` | `true` 或 `false` | | isChecked | Whether treeNode is checked | `boolean` | `true` / `false` | -| isAllChecked | Whether all treeNode's children are checked | `boolean` | `true` / `false` | | isHalfChecked | Part of treeNode's children are checked | `boolean` | `true` / `false` | | isSelected | Whether treeNode is selected | `boolean` | `true` / `false` | | isLoading | Whether treeNode is loading(when nzAsyncData is true) | `boolean` | `true` / `false` | diff --git a/components/tree/doc/index.zh-CN.md b/components/tree/doc/index.zh-CN.md index 27ee641f585..e45fcd511e6 100644 --- a/components/tree/doc/index.zh-CN.md +++ b/components/tree/doc/index.zh-CN.md @@ -114,7 +114,6 @@ subtitle: 树形控件 | isDisableCheckbox | 是否禁用 checkBox | `boolean` | `true` 或 `false` | | isSelectable | 是否可选中 | `boolean` | `true` 或 `false` | | isChecked | 是否选中 checkBox | `boolean` | `true` 或 `false` | -| isAllChecked | 子节点是否全选 | `boolean` | `true` 或 `false` | | isHalfChecked | 子节点有选中但未全选 | `boolean` | `true` 或 `false` | | isSelected | 是否已选中 | `boolean` | `true` 或 `false` | | isLoading | 是否异步加载状态(影响展开图标展示) | `boolean` | `true` 或 `false` | diff --git a/components/tree/nz-tree-base.service.ts b/components/tree/nz-tree-base.service.ts index 2d3f113b211..4d9fd23feef 100644 --- a/components/tree/nz-tree-base.service.ts +++ b/components/tree/nz-tree-base.service.ts @@ -19,10 +19,13 @@ export class NzTreeBaseService implements OnDestroy { checkedNodeList: NzTreeNode[] = []; halfCheckedNodeList: NzTreeNode[] = []; matchedNodeList: NzTreeNode[] = []; - $statusChange = new Subject(); + triggerEventChange$ = new Subject(); - statusChanged(): Observable { - return this.$statusChange.asObservable(); + /** + * trigger event + */ + eventTriggerChanged(): Observable { + return this.triggerEventChange$.asObservable(); } /** @@ -89,17 +92,17 @@ export class NzTreeBaseService implements OnDestroy { const calc = (nodes: NzTreeNode[]): boolean => { return nodes.every(node => { if (isInArray(node.key, selectedKeys)) { - node.setSelected(true, isMulti); + node.isSelected = true; if (!isMulti) { // if not support multi select return false; } } else { - node.setSelected(false, isMulti); + node.isSelected = false; } - if (node.getChildren().length > 0) { + if (node.children.length > 0) { // Recursion - return calc(node.getChildren()); + return calc(node.children); } return true; }); @@ -115,13 +118,12 @@ export class NzTreeBaseService implements OnDestroy { const calc = (nodes: NzTreeNode[]) => { nodes.forEach(node => { if (isInArray(node.key, expandedKeys)) { - node.setExpanded(true); - this.setExpandedNodeList(node); + node.isExpanded = true; } else { - node.setExpanded(false); + node.isExpanded = false; } - if (node.getChildren().length > 0) { - calc(node.getChildren()); + if (node.children.length > 0) { + calc(node.children); } }); }; @@ -137,12 +139,14 @@ export class NzTreeBaseService implements OnDestroy { const calc = (nodes: NzTreeNode[]) => { nodes.forEach(node => { if (isInArray(node.key, checkedKeys)) { - node.setChecked(true); + node.isChecked = true; + node.isHalfChecked = false; } else { - node.setChecked(false); + node.isChecked = false; + node.isHalfChecked = false; } - if (node.getChildren().length > 0) { - calc(node.getChildren()); + if (node.children.length > 0) { + calc(node.children); } }); }; @@ -164,19 +168,18 @@ export class NzTreeBaseService implements OnDestroy { /** * set node selected status */ - setNodeActive(node: NzTreeNode, isMultiple: boolean = false): void { - if (!isMultiple && node.isSelected) { + setNodeActive(node: NzTreeNode): void { + if (!this.isMultiple && node.isSelected) { this.selectedNodeList.forEach(n => { if (node.key !== n.key) { // reset other nodes - n.origin.selected = false; n.isSelected = false; } }); // single mode: remove pre node this.selectedNodeList = []; } - this.setSelectedNodeList(node, isMultiple); + this.setSelectedNodeList(node, this.isMultiple); } /** @@ -288,6 +291,7 @@ export class NzTreeBaseService implements OnDestroy { }); } + // reset other node checked state based current node conduct(node: NzTreeNode): void { const isChecked = node.isChecked; if (node) { @@ -306,14 +310,19 @@ export class NzTreeBaseService implements OnDestroy { // 全禁用节点不选中 if (parentNode) { if (!isCheckDisabled(parentNode)) { - if (parentNode.getChildren().every(child => isCheckDisabled(child) || (!child.isHalfChecked && child.isChecked))) { - parentNode.setChecked(true); - } else if (parentNode.getChildren().some(child => child.isHalfChecked || child.isChecked)) { - parentNode.setChecked(false, true); + if (parentNode.children.every(child => isCheckDisabled(child) || (!child.isHalfChecked && child.isChecked))) { + parentNode.isChecked = true; + parentNode.isHalfChecked = false; + } else if (parentNode.children.some(child => child.isHalfChecked || child.isChecked)) { + parentNode.isChecked = false; + parentNode.isHalfChecked = true; } else { - parentNode.setChecked(false); + parentNode.isChecked = false; + parentNode.isHalfChecked = false; } } + this.setCheckedNodeList(parentNode); + this.setHalfCheckedNodeList(parentNode); this.conductUp(parentNode); } } @@ -323,7 +332,10 @@ export class NzTreeBaseService implements OnDestroy { */ conductDown(node: NzTreeNode, value: boolean): void { if (!isCheckDisabled(node)) { - node.setChecked(value); + node.isChecked = value; + node.isHalfChecked = false; + this.setCheckedNodeList(node); + this.setHalfCheckedNodeList(node); node.children.forEach(n => { this.conductDown(n, value); }); @@ -358,7 +370,7 @@ export class NzTreeBaseService implements OnDestroy { } else { n.isMatched = false; } - n.getChildren().forEach(child => { + n.children.forEach(child => { searchChild(child); }); }; @@ -392,8 +404,8 @@ export class NzTreeBaseService implements OnDestroy { this.checkedNodeList.splice(index, 1); } - if (n.getChildren()) { - n.getChildren().forEach(child => { + if (n.children) { + n.children.forEach(child => { loopNode(child); }); } @@ -408,11 +420,11 @@ export class NzTreeBaseService implements OnDestroy { * drag event */ refreshDragNode(node: NzTreeNode): void { - if (node.getChildren().length === 0) { + if (node.children.length === 0) { // until root this.conductUp(node); } else { - node.getChildren().forEach((child) => { + node.children.forEach((child) => { this.refreshDragNode(child); }); } @@ -425,7 +437,7 @@ export class NzTreeBaseService implements OnDestroy { } else { node.level = 0; } - for (const child of node.getChildren()) { + for (const child of node.children) { this.resetNodeLevel(child); } } @@ -457,7 +469,7 @@ export class NzTreeBaseService implements OnDestroy { const isSelectedRootNode = this.selectedNode.getParentNode(); // remove the dragNode if (isSelectedRootNode) { - isSelectedRootNode.getChildren().splice(isSelectedRootNode.getChildren().indexOf(this.selectedNode), 1); + isSelectedRootNode.children.splice(isSelectedRootNode.children.indexOf(this.selectedNode), 1); } else { this.rootNodes.splice(this.rootNodes.indexOf(this.selectedNode), 1); } @@ -519,6 +531,7 @@ export class NzTreeBaseService implements OnDestroy { break; case 'check': const checkedNodeList = this.getCheckedNodeList(); + Object.assign(emitStructure, { 'checkedKeys': checkedNodeList }); Object.assign(emitStructure, { 'nodes': checkedNodeList }); Object.assign(emitStructure, { 'keys': checkedNodeList.map(n => n.key) }); @@ -537,8 +550,8 @@ export class NzTreeBaseService implements OnDestroy { } ngOnDestroy(): void { - this.$statusChange.complete(); - this.$statusChange = null; + this.triggerEventChange$.complete(); + this.triggerEventChange$ = null; } } diff --git a/components/tree/nz-tree-node.component.html b/components/tree/nz-tree-node.component.html index 00f2dfe56f2..3f75a241d73 100644 --- a/components/tree/nz-tree-node.component.html +++ b/components/tree/nz-tree-node.component.html @@ -31,16 +31,16 @@ @@ -90,11 +90,6 @@ [nzBeforeDrop]="nzBeforeDrop" [nzCheckStrictly]="nzCheckStrictly" [nzTreeTemplate]="nzTreeTemplate" - (clickNode)="clickNode.emit($event)" - (dblClick)="dblClick.emit($event)" - (contextMenu)="contextMenu.emit($event)" - (clickExpand)="clickExpand.emit($event)" - (clickCheckBox)="clickCheckBox.emit($event)" (nzDragStart)="nzDragStart.emit($event)" (nzDragEnter)="nzDragEnter.emit($event)" (nzDragOver)="nzDragOver.emit($event)" diff --git a/components/tree/nz-tree-node.component.ts b/components/tree/nz-tree-node.component.ts index 7d6ee2c1fdd..881d0b6fa1f 100644 --- a/components/tree/nz-tree-node.component.ts +++ b/components/tree/nz-tree-node.component.ts @@ -18,14 +18,13 @@ import { ViewChild } from '@angular/core'; import { fromEvent, Observable, Subject } from 'rxjs'; -import { takeUntil } from 'rxjs/operators'; +import { filter, takeUntil } from 'rxjs/operators'; import { collapseMotion } from '../core/animation/collapse'; import { NzNoAnimationDirective } from '../core/no-animation/nz-no-animation.directive'; import { InputBoolean } from '../core/util/convert'; import { NzFormatBeforeDropEvent, NzFormatEmitEvent } from '../tree/interface'; import { NzTreeBaseService } from './nz-tree-base.service'; import { NzTreeNode } from './nz-tree-node'; -import { isCheckDisabled } from './nz-tree-util'; @Component({ selector : 'nz-tree-node', @@ -38,6 +37,9 @@ import { isCheckDisabled } from './nz-tree-util'; export class NzTreeNodeComponent implements OnInit, OnChanges, OnDestroy { @ViewChild('dragElement') dragElement: ElementRef; + /** + * for global property + */ @Input() @InputBoolean() nzShowLine: boolean; @Input() @InputBoolean() nzShowExpand: boolean; @Input() @InputBoolean() nzMultiple: boolean; @@ -51,25 +53,7 @@ export class NzTreeNodeComponent implements OnInit, OnChanges, OnDestroy { @Input() nzTreeTemplate: TemplateRef; @Input() nzBeforeDrop: (confirm: NzFormatBeforeDropEvent) => Observable; - @Input() - set nzTreeNode(value: NzTreeNode) { - // add to checked list & selected list - if (value.isChecked) { - this.nzTreeService.setCheckedNodeList(value); - } - // add select list - if (value.isSelected) { - value.setSelected(true, this.nzMultiple); - } - if (!value.isLeaf) { - this.nzTreeService.setExpandedNodeList(value); - } - this._nzTreeNode = value; - } - - get nzTreeNode(): NzTreeNode { - return this._nzTreeNode; - } + @Input() nzTreeNode: NzTreeNode; @Input() set nzDraggable(value: boolean) { @@ -85,30 +69,10 @@ export class NzTreeNodeComponent implements OnInit, OnChanges, OnDestroy { * @deprecated use * nzExpandAll instead */ - @Input() - set nzDefaultExpandAll(value: boolean) { - this._nzExpandAll = value; - if (value && this.nzTreeNode && !this.nzTreeNode.isLeaf) { - this.nzTreeNode.setExpanded(true); - } - } - - get nzDefaultExpandAll(): boolean { - return this._nzExpandAll; - } + @Input() @InputBoolean() nzDefaultExpandAll; // default set - @Input() - set nzExpandAll(value: boolean) { - this._nzExpandAll = value; - if (value && this.nzTreeNode && !this.nzTreeNode.isLeaf) { - this.nzTreeNode.setExpanded(true); - } - } - - get nzExpandAll(): boolean { - return this._nzExpandAll; - } + @Input() @InputBoolean() nzExpandAll; @Input() set nzSearchValue(value: string) { @@ -116,8 +80,7 @@ export class NzTreeNodeComponent implements OnInit, OnChanges, OnDestroy { if (value && this.nzTreeNode.title.includes(value)) { // match the search value const index = this.nzTreeNode.title.indexOf(value); - this.highlightKeys.push(this.nzTreeNode.title.slice(0, index)); - this.highlightKeys.push(this.nzTreeNode.title.slice(index + value.length, this.nzTreeNode.title.length)); + this.highlightKeys = [ this.nzTreeNode.title.slice(0, index), this.nzTreeNode.title.slice(index + value.length, this.nzTreeNode.title.length) ]; } this._searchValue = value; } @@ -127,11 +90,6 @@ export class NzTreeNodeComponent implements OnInit, OnChanges, OnDestroy { } // Output - @Output() readonly clickNode: EventEmitter = new EventEmitter(); - @Output() readonly dblClick: EventEmitter = new EventEmitter(); - @Output() readonly contextMenu: EventEmitter = new EventEmitter(); - @Output() readonly clickCheckBox: EventEmitter = new EventEmitter(); - @Output() readonly clickExpand: EventEmitter = new EventEmitter(); @Output() readonly nzDragStart: EventEmitter = new EventEmitter(); @Output() readonly nzDragEnter: EventEmitter = new EventEmitter(); @Output() readonly nzDragOver: EventEmitter = new EventEmitter(); @@ -163,21 +121,19 @@ export class NzTreeNodeComponent implements OnInit, OnChanges, OnDestroy { /** * default set */ - _nzTreeNode: NzTreeNode; _searchValue = ''; - _nzExpandAll = false; _nzDraggable = false; oldAPIIcon = true; get nzIcon(): string { - if (this.nzTreeNode && this.nzTreeNode.origin.icon) { - this.oldAPIIcon = this.nzTreeNode.origin.icon.indexOf('anticon') > -1; + if (this.nzTreeNode.icon) { + this.oldAPIIcon = this.nzTreeNode.icon.indexOf('anticon') > -1; } - return this.nzTreeNode && this.nzTreeNode.origin.icon; + return this.nzTreeNode.icon; } get canDraggable(): boolean | null { - return (this.nzDraggable && this.nzTreeNode && !this.nzTreeNode.isDisabled) ? true : null; + return (this.nzDraggable && !this.nzTreeNode.isDisabled) ? true : null; } get isShowLineIcon(): boolean { @@ -263,18 +219,18 @@ export class NzTreeNodeComponent implements OnInit, OnChanges, OnDestroy { event.preventDefault(); event.stopPropagation(); if (this.nzTreeNode.isSelectable) { - this.nzTreeNode.setSelected(!this.nzTreeNode.isSelected, this.nzMultiple); + this.nzTreeNode.isSelected = !this.nzTreeNode.isSelected; } - const clickEvent = this.nzTreeService.formatEvent('click', this.nzTreeNode, event); - this.clickNode.emit(clickEvent); - this.nzTreeService.$statusChange.next(clickEvent); + const eventNext = this.nzTreeService.formatEvent('click', this.nzTreeNode, event); + this.nzTreeService.triggerEventChange$.next(eventNext); } @HostListener('dblclick', [ '$event' ]) nzDblClick(event: MouseEvent): void { event.preventDefault(); event.stopPropagation(); - this.dblClick.emit(this.nzTreeService.formatEvent('dblclick', this.nzTreeNode, event)); + const eventNext = this.nzTreeService.formatEvent('dblclick', this.nzTreeNode, event); + this.nzTreeService.triggerEventChange$.next(eventNext); } /** @@ -284,7 +240,8 @@ export class NzTreeNodeComponent implements OnInit, OnChanges, OnDestroy { nzContextMenu(event: MouseEvent): void { event.preventDefault(); event.stopPropagation(); - this.contextMenu.emit(this.nzTreeService.formatEvent('contextmenu', this.nzTreeNode, event)); + const eventNext = this.nzTreeService.formatEvent('contextmenu', this.nzTreeNode, event); + this.nzTreeService.triggerEventChange$.next(eventNext); } /** @@ -296,14 +253,12 @@ export class NzTreeNodeComponent implements OnInit, OnChanges, OnDestroy { event.stopPropagation(); if (!this.nzTreeNode.isLoading && !this.nzTreeNode.isLeaf) { // set async state - if (this.nzAsyncData && this.nzTreeNode.getChildren().length === 0 && !this.nzTreeNode.isExpanded) { + if (this.nzAsyncData && this.nzTreeNode.children.length === 0 && !this.nzTreeNode.isExpanded) { this.nzTreeNode.isLoading = true; } - this.nzTreeNode.setExpanded(!this.nzTreeNode.isExpanded); - const expandEvent = this.nzTreeService.formatEvent('expand', this.nzTreeNode, event); - this.clickExpand.emit(expandEvent); - // just affect self - this.setClassMap(); + this.nzTreeNode.isExpanded = !this.nzTreeNode.isExpanded; + const eventNext = this.nzTreeService.formatEvent('expand', this.nzTreeNode, event); + this.nzTreeService.triggerEventChange$.next(eventNext); } } @@ -315,13 +270,16 @@ export class NzTreeNodeComponent implements OnInit, OnChanges, OnDestroy { event.preventDefault(); event.stopPropagation(); // return if node is disabled - if (isCheckDisabled(this.nzTreeNode)) { + if (this.nzTreeNode.isDisabled || this.nzTreeNode.isDisableCheckbox) { return; } - this.nzTreeNode.setSyncChecked(!this.nzTreeNode.isChecked); - const checkBoxChangeEvent = this.nzTreeService.formatEvent('check', this.nzTreeNode, event); - this.clickCheckBox.emit(checkBoxChangeEvent); - this.nzTreeService.$statusChange.next(checkBoxChangeEvent); + this.nzTreeNode.isChecked = !this.nzTreeNode.isChecked; + this.nzTreeNode.isHalfChecked = false; + if (!this.nzTreeService.isCheckStrictly) { + this.nzTreeService.conduct(this.nzTreeNode); + } + const eventNext = this.nzTreeService.formatEvent('check', this.nzTreeNode, event); + this.nzTreeService.triggerEventChange$.next(eventNext); } /** @@ -345,7 +303,7 @@ export class NzTreeNodeComponent implements OnInit, OnChanges, OnDestroy { // empty } this.nzTreeService.setSelectedNode(this.nzTreeNode); - this.nzTreeNode.setExpanded(false); + this.nzTreeNode.isExpanded = false; this.nzDragStart.emit(this.nzTreeService.formatEvent('dragstart', null, e)); } @@ -355,13 +313,13 @@ export class NzTreeNodeComponent implements OnInit, OnChanges, OnDestroy { // reset position this.dragPos = 2; this.ngZone.run(() => { - if ((this.nzTreeNode !== this.nzTreeService.getSelectedNode()) && !this.nzTreeNode.isLeaf) { - this.nzTreeNode.setExpanded(true); + if ((this.key !== this.nzTreeService.getSelectedNode().key) && !this.nzTreeNode.isLeaf) { + this.nzTreeNode.isExpanded = true; } }); const dragEnterEvent = this.nzTreeService.formatEvent('dragenter', this.nzTreeNode, e); + this.nzTreeService.triggerEventChange$.next(dragEnterEvent); this.nzDragEnter.emit(dragEnterEvent); - this.nzTreeService.$statusChange.next(dragEnterEvent); } handleDragOver(e: DragEvent): void { @@ -392,7 +350,7 @@ export class NzTreeNodeComponent implements OnInit, OnChanges, OnDestroy { e.stopPropagation(); this.ngZone.run(() => { this.clearDragClass(); - if (this.nzTreeService.getSelectedNode() === this.nzTreeNode) { + if (this.nzTreeService.getSelectedNode().key === this.nzTreeNode.key) { return; } else if (this.dragPos === 0 && this.nzTreeNode.isLeaf) { return; @@ -409,14 +367,14 @@ export class NzTreeNodeComponent implements OnInit, OnChanges, OnDestroy { if (canDrop) { this.nzTreeService.dropAndApply(this.nzTreeNode, this.dragPos); } + this.nzTreeService.triggerEventChange$.next(dropEvent); this.nzDrop.emit(dropEvent); this.nzDragEnd.emit(dragEndEvent); - this.nzTreeService.$statusChange.next(dropEvent); }); } else if (this.nzTreeNode) { this.nzTreeService.dropAndApply(this.nzTreeNode, this.dragPos); + this.nzTreeService.triggerEventChange$.next(dropEvent); this.nzDrop.emit(dropEvent); - this.nzTreeService.$statusChange.next(dropEvent); } }); } @@ -453,6 +411,14 @@ export class NzTreeNodeComponent implements OnInit, OnChanges, OnDestroy { }); } + formatEvent(eventName: string, node: NzTreeNode, event: MouseEvent | DragEvent): NzFormatEmitEvent { + return { + 'eventName': eventName, + 'node' : node, + 'event' : event + }; + } + markForCheck(): void { this.cdr.markForCheck(); } @@ -467,13 +433,27 @@ export class NzTreeNodeComponent implements OnInit, OnChanges, OnDestroy { } ngOnInit(): void { - this.setClassMap(); + // init expanded / selected / checked list + this.nzTreeNode.isSelected = this.nzTreeNode.isSelected; + if (this.nzDefaultExpandAll || this.nzExpandAll) { + this.nzTreeNode.isExpanded = this.nzExpandAll; + // this.isExpanded = true; + } else { + this.nzTreeNode.isExpanded = this.nzTreeNode.isExpanded; + } + if (this.nzTreeNode.isChecked) { + this.nzTreeService.setCheckedNodeList(this.nzTreeNode); + } // TODO - this.nzTreeNode.setComponent(this); - this.nzTreeService.statusChanged().pipe(takeUntil(this.destroy$)).subscribe(() => { + this.nzTreeNode.component = this; + this.nzTreeService.eventTriggerChanged().pipe( + filter(data => data.node.key === this.nzTreeNode.key), + takeUntil(this.destroy$) + ).subscribe(() => { this.setClassMap(); this.markForCheck(); }); + this.setClassMap(); } ngOnChanges(): void { diff --git a/components/tree/nz-tree-node.ts b/components/tree/nz-tree-node.ts index dcdb8467cb2..c570095319b 100644 --- a/components/tree/nz-tree-node.ts +++ b/components/tree/nz-tree-node.ts @@ -19,34 +19,34 @@ export interface NzTreeNodeOptions { } export class NzTreeNode { - title?: string; - key: string; - level: number = 0; - children: NzTreeNode[]; - isLeaf: boolean; + private _title: string; + private _key: string; + private _icon: string; + private _level: number = 0; + private _children: NzTreeNode[]; + private _isLeaf: boolean; // tslint:disable-next-line:no-any - origin: any; + private _origin: any; // Parent Node - parentNode: NzTreeNode; - isChecked: boolean; - isSelectable: boolean; - isDisabled: boolean; - isDisableCheckbox: boolean; - isExpanded: boolean; - isHalfChecked: boolean; - isAllChecked: boolean; - isSelected: boolean; - isLoading: boolean; - isMatched: boolean; + private _parentNode: NzTreeNode; + private _isChecked: boolean; + private _isSelectable: boolean; + private _isDisabled: boolean; + private _isDisableCheckbox: boolean; + private _isExpanded: boolean; + private _isHalfChecked: boolean; + private _isSelected: boolean; + private _isLoading: boolean; + private _isMatched: boolean; private readonly service: NzTreeBaseService; - private component: NzTreeNodeComponent; + private _component: NzTreeNodeComponent; get treeService(): NzTreeBaseService { if (this.service) { return this.service; - } else if (this.parentNode) { - return this.parentNode.treeService; + } else if (this._parentNode) { + return this._parentNode.treeService; } } @@ -55,31 +55,32 @@ export class NzTreeNode { return option; } this.service = service; - this.title = option.title || '---'; - this.key = option.key || null; - this.isLeaf = option.isLeaf || false; - this.origin = option; - this.children = []; - this.parentNode = parent; + this._title = option.title || '---'; + this._key = option.key || null; + this._icon = option.icon || ''; + this._isLeaf = option.isLeaf || false; + this._origin = option; + this._children = []; + this._parentNode = parent; // option params - this.isChecked = option.checked || false; - this.isSelectable = option.disabled || (option.selectable === false ? false : true); - this.isDisabled = option.disabled || false; - this.isDisableCheckbox = option.disableCheckbox || false; - this.isExpanded = option.isLeaf ? false : (option.expanded || false); - this.isAllChecked = option.checked || false; - this.isHalfChecked = false; - this.isSelected = (!option.disabled && option.selected) || false; - this.isLoading = false; - this.isMatched = false; + this._isChecked = option.checked || false; + this._isSelectable = option.disabled || (option.selectable === false ? false : true); + this._isDisabled = option.disabled || false; + this._isDisableCheckbox = option.disableCheckbox || false; + this._isExpanded = option.isLeaf ? false : (option.expanded || false); + this._isAllChecked = option.checked || false; + this._isHalfChecked = false; + this._isSelected = (!option.disabled && option.selected) || false; + this._isLoading = false; + this._isMatched = false; /** * parent's checked status will affect children while initializing */ if (parent) { - this.level = parent.level + 1; + this._level = parent._level + 1; } else { - this.level = 0; + this._level = 0; } if (typeof (option.children) !== 'undefined' && option.children !== null) { option.children.forEach( @@ -87,59 +88,189 @@ export class NzTreeNode { if ((this.treeService && !this.treeService.isCheckStrictly) && option.checked && !option.disabled && !nodeOptions.disabled && !nodeOptions.disableCheckbox) { nodeOptions.checked = option.checked; } - this.children.push(new NzTreeNode(nodeOptions, this)); + this._children.push(new NzTreeNode(nodeOptions, this)); } ); } } - public setComponent(component: NzTreeNodeComponent): void { - this.component = component; + /** + * auto generate + * get + * set + */ + get component(): NzTreeNodeComponent { + return this._component; } - public setSyncChecked(checked: boolean = false, halfChecked: boolean = false): void { - this.setChecked(checked, halfChecked); - if (!this.treeService.isCheckStrictly) { - this.treeService.conduct(this); - } + set component(value: NzTreeNodeComponent) { + this._component = value; } - public setChecked(checked: boolean = false, halfChecked: boolean = false): void { - this.origin.checked = checked; - this.isChecked = checked; - this.isAllChecked = checked; - this.isHalfChecked = halfChecked; - if (this.treeService) { - this.treeService.setCheckedNodeList(this); - this.treeService.setHalfCheckedNodeList(this); - this.treeService.$statusChange.next({ - 'eventName': 'setChecked', - 'node' : this - }); - } + get title(): string { + return this._title; + } + + set title(value: string) { + this._title = value; + this.update(); + } + + get key(): string { + return this._key; + } + + set key(value: string) { + this._key = value; + } + + get icon(): string { + return this._icon; + } + + set icon(value: string) { + this._icon = value; + this.update(); + } + + get level(): number { + return this._level; + } + + set level(value: number) { + this._level = value; + } + + get children(): NzTreeNode[] { + return this._children; + } + + set children(value: NzTreeNode[]) { + this._children = value; + this.update(); + } + + // tslint:disable-next-line:no-any + get origin(): any { + return this._origin; + } + + // tslint:disable-next-line:no-any + set origin(value: any) { + this._origin = value; + } + + get parentNode(): NzTreeNode { + return this._parentNode; + } + + set parentNode(value: NzTreeNode) { + this._parentNode = value; + } + + get isLeaf(): boolean { + return this._isLeaf; + } + + set isLeaf(value: boolean) { + this._isLeaf = value; + this.update(); + } + + get isChecked(): boolean { + return this._isChecked; } - public setExpanded(value: boolean): void { - this.origin.expanded = value; - this.isExpanded = value; + set isChecked(value: boolean) { + this._isChecked = value; + this._origin.checked = value; + this.treeService.setCheckedNodeList(this); + this.update(); + } + + get isHalfChecked(): boolean { + return this._isHalfChecked; + } + + set isHalfChecked(value: boolean) { + this._isHalfChecked = value; + this.treeService.setHalfCheckedNodeList(this); + this.update(); + } + + get isSelectable(): boolean { + return this._isSelectable; + } + + set isSelectable(value: boolean) { + this._isSelectable = value; + this.update(); + } + + get isDisabled(): boolean { + return this._isDisabled; + } + + set isDisabled(value: boolean) { + this._isDisabled = value; + this.update(); + } + + get isDisableCheckbox(): boolean { + return this._isDisableCheckbox; + } + + set isDisableCheckbox(value: boolean) { + this._isDisableCheckbox = value; + this.update(); + } + + get isExpanded(): boolean { + return this._isExpanded; + } + + set isExpanded(value: boolean) { + this._isExpanded = value; + this._origin.expanded = value; this.treeService.setExpandedNodeList(this); - if (this.component) { - this.component.markForCheck(); - } + this.update(); } - public setSelected(value: boolean, isMultiple: boolean = this.treeService.isMultiple): void { - if (this.isDisabled) { - return; - } - this.origin.selected = value; - this.isSelected = value; - this.treeService.setNodeActive(this, isMultiple); - if (this.component) { - this.component.markForCheck(); - } + get isSelected(): boolean { + return this._isSelected; + } + + set isSelected(value: boolean) { + this._isSelected = value; + this._origin.selected = value; + this.treeService.setNodeActive(this); + this.update(); + } + + get isLoading(): boolean { + return this._isLoading; + } + + set isLoading(value: boolean) { + this._isLoading = value; + this.update(); + } + + get isMatched(): boolean { + return this._isMatched; + } + + set isMatched(value: boolean) { + this._isMatched = value; + this.update(); } + /** + * end + * get + * set + */ + public getParentNode(): NzTreeNode { return this.parentNode; } @@ -182,7 +313,7 @@ export class NzTreeNode { this.origin.children = this.getChildren().map(v => v.origin); // remove loading state this.isLoading = false; - this.treeService.$statusChange.next({ + this.treeService.triggerEventChange$.next({ 'eventName': 'addChildren', 'node' : this }); @@ -197,9 +328,7 @@ export class NzTreeNode { this.origin.children = []; // refresh checked state this.treeService.calcCheckedKeys(this.treeService.checkedNodeList.map(v => v.key), this.treeService.rootNodes, this.treeService.isCheckStrictly); - if (this.component) { - this.component.markForCheck(); - } + this.update(); } public remove(): void { @@ -208,9 +337,13 @@ export class NzTreeNode { this.getParentNode().getChildren().splice(index, 1); this.getParentNode().origin.children.splice(index, 1); this.treeService.afterRemove(this); - if (this.component) { - this.component.markForCheck(); - } + this.update(); + } + } + + public update(): void { + if (this._component) { + this._component.markForCheck(); } } } diff --git a/components/tree/nz-tree.component.html b/components/tree/nz-tree.component.html index 1dedde83d84..4c6cf1ebfac 100644 --- a/components/tree/nz-tree.component.html +++ b/components/tree/nz-tree.component.html @@ -21,11 +21,6 @@ [nzShowIcon]="nzShowIcon" [nzTreeTemplate]="nzTreeTemplate" [nzNoAnimation]="noAnimation?.nzNoAnimation" - (clickNode)="nzClick.emit($event)" - (dblClick)="nzDblClick.emit($event)" - (contextMenu)="nzContextMenu.emit($event)" - (clickExpand)="nzExpandChange.emit($event)" - (clickCheckBox)="nzCheckBoxChange.emit($event)" (nzDragStart)="nzOnDragStart.emit($event)" (nzDragEnter)="nzOnDragEnter.emit($event)" (nzDragOver)="nzOnDragOver.emit($event)" diff --git a/components/tree/nz-tree.component.ts b/components/tree/nz-tree.component.ts index 6383d2114c1..f86c564caaa 100644 --- a/components/tree/nz-tree.component.ts +++ b/components/tree/nz-tree.component.ts @@ -17,7 +17,8 @@ import { TemplateRef } from '@angular/core'; import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; -import { Observable, ReplaySubject, Subscription } from 'rxjs'; +import { Observable, ReplaySubject, Subject, Subscription } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; import { NzNoAnimationDirective } from '../core/no-animation/nz-no-animation.directive'; import { isNotNil } from '../core/util/check'; import { InputBoolean } from '../core/util/convert'; @@ -66,14 +67,14 @@ export class NzTreeComponent implements OnInit, OnChanges, OnDestroy, ControlVal @Input() @InputBoolean() nzAsyncData = false; @Input() @InputBoolean() nzDraggable = false; @Input() @InputBoolean() nzMultiple = false; - @Input() @InputBoolean() nzExpandAll: boolean = false; + @Input() @InputBoolean() nzExpandAll = false; @Input() @InputBoolean() nzHideUnMatched = false; @Input() @InputBoolean() nzSelectMode = false; /** * @deprecated use * nzExpandAll instead */ - @Input() @InputBoolean() nzDefaultExpandAll: boolean = false; + @Input() @InputBoolean() nzDefaultExpandAll = false; @Input() nzBeforeDrop: (confirm: NzFormatBeforeDropEvent) => Observable; @Input() @@ -182,6 +183,7 @@ export class NzTreeComponent implements OnInit, OnChanges, OnDestroy, ControlVal _searchValue = null; nzDefaultSubject = new ReplaySubject<{ type: string, keys: string[] }>(6); nzDefaultSubscription: Subscription; + destroy$ = new Subject(); nzNodes: NzTreeNode[] = []; prefixCls = 'ant-tree'; classMap = {}; @@ -300,6 +302,27 @@ export class NzTreeComponent implements OnInit, OnChanges, OnDestroy, ControlVal } this.cdr.markForCheck(); }); + this.nzTreeService.eventTriggerChanged().pipe( + takeUntil(this.destroy$) + ).subscribe(data => { + switch (data.eventName) { + case 'expand': + this.nzExpandChange.emit(data); + break; + case 'click': + this.nzClick.emit(data); + break; + case 'check': + this.nzCheckBoxChange.emit(data); + break; + case 'dblclick': + this.nzDblClick.emit(data); + break; + case 'contextmenu': + this.nzContextMenu.emit(data); + break; + } + }); } ngOnChanges(changes: { [ propertyName: string ]: SimpleChange }): void { @@ -312,6 +335,9 @@ export class NzTreeComponent implements OnInit, OnChanges, OnDestroy, ControlVal } ngOnDestroy(): void { + this.destroy$.next(); + this.destroy$.complete(); + this.destroy$ = null; if (this.nzDefaultSubscription) { this.nzDefaultSubscription.unsubscribe(); this.nzDefaultSubscription = null;