Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(tree): support nzHideUnMatched #2217

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions components/tree-select/demo/basic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { NzFormatEmitEvent, NzTreeNode } from 'ng-zorro-antd';
style="width: 250px"
[nzDefaultExpandedKeys]="expandKeys"
[nzNodes]="nodes"
nzHideUnMatched
nzShowSearch
nzPlaceHolder="Please select"
[(ngModel)]="value"
Expand Down
2 changes: 1 addition & 1 deletion components/tree-select/demo/multiple.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { NzFormatEmitEvent, NzTreeNode } from 'ng-zorro-antd';

export class NzDemoTreeSelectMultipleComponent implements OnInit {

value: string[] = [];
value: string[] = ['100'];
nodes = [ {
title : 'parent 1',
key : '100',
Expand Down
1 change: 1 addition & 0 deletions components/tree-select/doc/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Any data whose entries are defined in a hierarchical manner is fit to use this c
| `[nzPlaceHolder]` | Placeholder of the select input | string | - |
| `[nzDisabled]` | Disabled or not | boolean | false |
| `[nzShowSearch]` | Whether to display a search input in the dropdown menu(valid only in the single mode) | boolean | false |
| `[nzHideUnMatched]` | hide unMatched treeNodes | boolean | false |
| `[nzDropdownMatchSelectWidth]` | Determine whether the dropdown menu and the select input are the same width | boolean | true |
| `[nzDropdownStyle]` | To set the style of the dropdown menu | object | - |
| `[nzMultiple]` | Support multiple or not, will be `true` when enable `nzCheckable`. | boolean | false |
Expand Down
1 change: 1 addition & 0 deletions components/tree-select/doc/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ title: TreeSelect
| `[nzPlaceHolder]` | 选择框默认文字 | string | - |
| `[nzDisabled]` | 禁用选择器 | boolean | false |
| `[nzShowSearch]` | 显示搜索框 | boolean | false |
| `[nzHideUnMatched]` | 隐藏未匹配的节点 | boolean | false |
| `[nzDropdownMatchSelectWidth]` | 下拉菜单和选择器同宽 | boolean | true |
| `[nzDropdownStyle]` | 下拉菜单的样式 | { [key: string]: string; } | - |
| `[nzMultiple]` | 支持多选(当设置 nzCheckable 时自动变为true) | boolean | false |
Expand Down
20 changes: 19 additions & 1 deletion components/tree-select/nz-tree-select.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@
[ngStyle]="nzDropdownStyle">
<nz-tree
#treeRef
[style.display]="isEmpty?'none':''"
[nzData]="nzNodes"
[nzMultiple]="nzMultiple"
[nzSearchValue]="inputValue"
[nzHideUnMatched]="nzHideUnMatched"
[nzCheckable]="nzCheckable"
[nzAsyncData]="nzAsyncData"
[nzShowExpand]="nzShowExpand"
Expand All @@ -29,8 +31,24 @@
[nzSelectedKeys]="!nzCheckable ? value : []"
(nzExpandChange)="nzExpandChange.emit($event)"
(nzClick)="nzTreeClick.emit($event)"
(nzCheckBoxChange)="nzTreeCheckBoxChange.emit($event)">
(nzCheckBoxChange)="nzTreeCheckBoxChange.emit($event)"
(nzSearchValueChange)="searchChange$.next($event)">
</nz-tree>
<ng-container *ngIf="isEmpty">
<div role="listbox" tabindex="-1">
<span class="ant-select-not-found">
<ng-container *ngIf="!nzNoResult">
{{locale.notFoundContent}}
</ng-container>
<ng-container *ngIf="nzNoResult">
<ng-container *ngIf="isNoResultString; else noResultTemplate">{{nzNoResult}}</ng-container>
<ng-template #noResultTemplate>
<ng-template [ngTemplateOutlet]="nzNoResult"></ng-template>
</ng-template>
</ng-container>
</span>
</div>
</ng-container>
</div>
</ng-template>

Expand Down
50 changes: 45 additions & 5 deletions components/tree-select/nz-tree-select.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,15 @@ import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';

import {
merge,
of as observableOf,
of as observableOf, Subject,
Subscription
} from 'rxjs';
import { filter, tap } from 'rxjs/operators';
import { filter, takeUntil, tap } from 'rxjs/operators';

import { selectDropDownAnimation } from '../core/animation/select-dropdown-animations';
import { selectTagAnimation } from '../core/animation/select-tag-animations';
import { InputBoolean } from '../core/util/convert';
import { NzI18nService } from '../i18n/nz-i18n.service';
import { NzFormatEmitEvent } from '../tree/interface';
import { NzTreeNode } from '../tree/nz-tree-node';
import { NzTreeComponent } from '../tree/nz-tree.component';
Expand Down Expand Up @@ -79,6 +80,14 @@ import { NzTreeComponent } from '../tree/nz-tree.component';
export class NzTreeSelectComponent implements ControlValueAccessor, OnInit, AfterViewInit, OnDestroy {

private nodes = [];
private _noResult: string | TemplateRef<void>;
private unsubscribe$ = new Subject<void>();
searchChange$ = new Subject<NzFormatEmitEvent>();
isEmpty = false;
isNoResultString: boolean;
/* tslint:disable-next-line:no-any */
locale: any = {};

isComposing = false;
isDestroy = true;
inputValue = '';
Expand All @@ -98,6 +107,7 @@ export class NzTreeSelectComponent implements ControlValueAccessor, OnInit, Afte
@Input() @InputBoolean() nzDropdownMatchSelectWidth = true;
@Input() @InputBoolean() nzCheckable = false;
@Input() @InputBoolean() nzShowSearch = false;
@Input() @InputBoolean() nzHideUnMatched = false;
@Input() @InputBoolean() nzDisabled = false;
@Input() @InputBoolean() nzShowLine = false;
@Input() @InputBoolean() nzAsyncData = false;
Expand All @@ -117,17 +127,34 @@ export class NzTreeSelectComponent implements ControlValueAccessor, OnInit, Afte
@Output() nzTreeCheckBoxChange = new EventEmitter<NzFormatEmitEvent>();

@Input()
set nzNodes(value: NzTreeNode[]) {
// tslint:disable-next-line:no-any
set nzNodes(value: any[]) {
this.nodes = value;
if (value.length === 0) {
this.isEmpty = true;
} else {
this.isEmpty = false;
}
if (this.treeRef) {
setTimeout(() => this.updateSelectedNodes(), 0);
}
}

get nzNodes(): NzTreeNode[] {
// tslint:disable-next-line:no-any
get nzNodes(): any[] {
return this.nodes;
}

@Input()
set nzNoResult(value: string | TemplateRef<void>) {
this.isNoResultString = !(value instanceof TemplateRef);
this._noResult = value;
}

get nzNoResult(): string | TemplateRef<void> {
return this._noResult;
}

@ViewChild('inputElement') inputElement: ElementRef;
@ViewChild('treeSelect') treeSelect: ElementRef;
@ViewChild('dropdownTemplate', { read: TemplateRef }) dropdownTemplate;
Expand Down Expand Up @@ -175,7 +202,8 @@ export class NzTreeSelectComponent implements ControlValueAccessor, OnInit, Afte
private renderer: Renderer2,
private cdr: ChangeDetectorRef,
private overlay: Overlay,
private viewContainerRef: ViewContainerRef) {
private viewContainerRef: ViewContainerRef,
private i18n: NzI18nService) {
}

@HostListener('click')
Expand Down Expand Up @@ -422,6 +450,16 @@ export class NzTreeSelectComponent implements ControlValueAccessor, OnInit, Afte
ngOnInit(): void {
this.isDestroy = false;
this.selectionChangeSubscription = this.subscribeSelectionChange();
// to set i18n
this.i18n.localeChange.pipe(takeUntil(this.unsubscribe$)).subscribe(() => this.locale = this.i18n.getLocaleData('Select'));
// to get search result
this.searchChange$.pipe(takeUntil(this.unsubscribe$)).subscribe((result) => {
if (result.nodes.length > 0 || !this.inputValue) {
this.isEmpty = false;
} else if (result.nodes.length === 0) {
this.isEmpty = true;
}
});
Promise.resolve().then(() => {
this.updateDropDownClassMap();
this.updateCdkConnectedOverlayStatus();
Expand All @@ -431,6 +469,8 @@ export class NzTreeSelectComponent implements ControlValueAccessor, OnInit, Afte
ngOnDestroy(): void {
this.isDestroy = true;
this.detachOverlay();
this.unsubscribe$.next();
this.unsubscribe$.complete();
this.selectionChangeSubscription.unsubscribe();
this.overlayBackdropClickSubscription.unsubscribe();
}
Expand Down
3 changes: 2 additions & 1 deletion components/tree-select/nz-tree-select.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ import { OverlayModule } from '@angular/cdk/overlay';
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { NzI18nModule } from '../i18n/nz-i18n.module';
import { NzTreeModule } from '../tree/nz-tree.module';
import { NzTreeSelectComponent } from './nz-tree-select.component';

@NgModule({
imports : [ CommonModule, OverlayModule, FormsModule, NzTreeModule ],
imports : [ CommonModule, OverlayModule, FormsModule, NzTreeModule, NzI18nModule ],
declarations: [ NzTreeSelectComponent ],
exports : [ NzTreeSelectComponent ]
})
Expand Down
51 changes: 51 additions & 0 deletions components/tree-select/nz-tree-select.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,55 @@ describe('tree-select component', () => {
tick();
expect(treeSelect.nativeElement.querySelector('.ant-select-search--inline')).toBeNull();
}));

it('should set empty value work', fakeAsync(() => {
treeSelectComponent.updateSelectedNodes();
fixture.detectChanges();
testComponent.showSearch = true;
fixture.detectChanges();
treeSelect.nativeElement.click();
fixture.detectChanges();
const inputEl = treeSelect.nativeElement.querySelector('.ant-select-search__field');
inputEl.value = 'test';
dispatchFakeEvent(inputEl, 'input');
fixture.detectChanges();
flush();
fixture.detectChanges();
const overlayPane = overlayContainerElement.querySelector('.cdk-overlay-pane') as HTMLElement;
// test option empty
expect(overlayPane.querySelector('.ant-select-not-found')).toBeDefined();
}));

it('should set empty nodes work', fakeAsync(() => {
treeSelectComponent.updateSelectedNodes();
fixture.detectChanges();
testComponent.nodes = [];
tick(500);
fixture.detectChanges();
treeSelect.nativeElement.click();
fixture.detectChanges();
flush();
fixture.detectChanges();
const overlayPane = overlayContainerElement.querySelector('.cdk-overlay-pane') as HTMLElement;
expect(overlayPane.querySelector('.ant-select-not-found')).toBeDefined();
}));

it('should set nzNoResult work', fakeAsync(() => {
treeSelectComponent.updateSelectedNodes();
fixture.detectChanges();
testComponent.nodes = [];
testComponent.noResult = 'test';
tick(500);
fixture.detectChanges();
treeSelect.nativeElement.click();
fixture.detectChanges();
flush();
fixture.detectChanges();
const overlayPane = overlayContainerElement.querySelector('.cdk-overlay-pane') as HTMLElement;
expect(overlayPane.querySelector('.ant-select-not-found')).toBeDefined();
expect(overlayPane.querySelector('.ant-select-not-found').innerHTML).toContain('test');
}));

it('should selectedValueDisplay style correct', fakeAsync(() => {
testComponent.showSearch = true;
fixture.detectChanges();
Expand Down Expand Up @@ -356,12 +405,14 @@ describe('tree-select component', () => {
[nzDropdownMatchSelectWidth]="dropdownMatchSelectWidth"
[nzDisabled]="disabled"
[nzShowSearch]="showSearch"
[nzNoResult]="noResult"
[nzDropdownStyle]="{ 'height': '120px' }">
</nz-tree-select>
`
})
export class NzTestTreeSelectBasicComponent {
@ViewChild(NzTreeSelectComponent) nzSelectTreeComponent: NzTreeSelectComponent;
noResult = '';
expandKeys = [ '1001', '10001' ];
value = '10001';
size = 'default';
Expand Down
1 change: 1 addition & 0 deletions components/tree/doc/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ Almost anything can be represented in a tree structure. Examples include directo
| `[nzCheckedKeys]` | Specifies the keys of the default checked treeNodes, two-way binding | string\[] | \[] |
| `[nzSelectedKeys]` | Specifies the keys of the default selected treeNodes, two-way binding | string\[] | \[] |
| `[nzSearchValue]` | Filter (highlight) treeNodes (see demo `Searchable`), two-way binding | string | null |
| `[nzHideUnMatched]` | hide unMatched(highlight) treeNodes(used with nzSearchValue) | boolean | false |
| `[nzBeforeDrop]` | Drop before the second check, allowing the user to decide whether to allow placement | `(confirm: NzFormatBeforeDropEvent) => Observable<boolean>` | - |
| `(nzClick)` | Callback function for when the user clicks a treeNode | EventEmitter<NzFormatEmitEvent\> | - |
| `(nzDblClick)` | Callback function for when the user double clicks a treeNode | EventEmitter<NzFormatEmitEvent\> | - |
Expand Down
1 change: 1 addition & 0 deletions components/tree/doc/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ subtitle: 树形控件
| `[nzCheckedKeys]` | 指定选中复选框的树节点,双向绑定 | string\[] | \[] |
| `[nzSelectedKeys]` | 指定选中的树节点,双向绑定 | string\[] | \[] |
| `[nzSearchValue]` | 按需筛选树高亮节点(参考可搜索的树),双向绑定 | string | null |
| `[nzHideUnMatched]` | 隐藏未匹配的节点,与nzSearchValue配合使用 | boolean | false |
| `[nzBeforeDrop]` | drop前二次校验,允许用户自行决定是否允许放置 | `(confirm: NzFormatBeforeDropEvent) => Observable<boolean>` | - |
| `(nzClick)` | 点击树节点触发 | EventEmitter<NzFormatEmitEvent\> | - |
| `(nzDblClick)` | 双击树节点触发 | EventEmitter<NzFormatEmitEvent\> | - |
Expand Down
2 changes: 2 additions & 0 deletions components/tree/nz-tree-node.component.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<li
#dragElement
role="treeitem"
[style.display]="displayStyle"
[ngClass]="nzNodeClass"
[class.ant-tree-treenode-switcher-open]="isSwitcherOpen"
[class.ant-tree-treenode-switcher-close]="isSwitcherClose"
Expand Down Expand Up @@ -81,6 +82,7 @@
[nzExpandAll]="nzExpandAll"
[nzDefaultExpandAll]="nzDefaultExpandAll"
[nzSearchValue]="nzSearchValue"
[nzHideUnMatched]="nzHideUnMatched"
[nzBeforeDrop]="nzBeforeDrop"
[nzCheckStrictly]="nzCheckStrictly"
[nzTreeTemplate]="nzTreeTemplate"
Expand Down
10 changes: 6 additions & 4 deletions components/tree/nz-tree-node.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export class NzTreeNodeComponent implements OnInit, OnChanges {
@Input() @InputBoolean() nzCheckable: boolean;
@Input() @InputBoolean() nzAsyncData: boolean;
@Input() @InputBoolean() nzCheckStrictly: boolean;
@Input() @InputBoolean() nzHideUnMatched = false;
@Input() nzTreeTemplate: TemplateRef<void>;
@Input() nzBeforeDrop: (confirm: NzFormatBeforeDropEvent) => Observable<boolean>;

Expand Down Expand Up @@ -103,14 +104,10 @@ export class NzTreeNodeComponent implements OnInit, OnChanges {
set nzSearchValue(value: string) {
this.highlightKeys = [];
if (value && this.nzTreeNode.title.includes(value)) {
this.nzTreeNode.isMatched = true;
// 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));
} else {
// close the node if title does't contain search value
this.nzTreeNode.isMatched = false;
}
this._searchValue = value;
}
Expand Down Expand Up @@ -171,6 +168,11 @@ export class NzTreeNodeComponent implements OnInit, OnChanges {
return (!this.nzTreeNode.isExpanded && !this.nzTreeNode.isLeaf);
}

get displayStyle(): string {
// TODO
return (this.nzSearchValue && this.nzHideUnMatched && !this.nzTreeNode.isMatched && !this.nzTreeNode.isExpanded) ? 'none' : '';
}

/**
* reset node class
*/
Expand Down
1 change: 1 addition & 0 deletions components/tree/nz-tree.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
[nzAsyncData]="nzAsyncData"
[nzMultiple]="nzMultiple"
[nzSearchValue]="nzSearchValue"
[nzHideUnMatched]="nzHideUnMatched"
[nzBeforeDrop]="nzBeforeDrop"
[nzCheckStrictly]="nzCheckStrictly"
[nzExpandAll]="nzExpandAll"
Expand Down
Loading