From 4081abb8f2038deda55217f46342762a1d7e2cae Mon Sep 17 00:00:00 2001 From: Hsuan Lee Date: Tue, 26 Feb 2019 15:59:32 +0800 Subject: [PATCH] feat(module:tree-select): support set the max count for tags (#2970) close #2488 --- components/select/doc/index.en-US.md | 2 ++ components/select/doc/index.zh-CN.md | 2 ++ components/tree-select/demo/multiple.md | 4 ++-- components/tree-select/demo/multiple.ts | 7 +++++- components/tree-select/doc/index.en-US.md | 2 ++ components/tree-select/doc/index.zh-CN.md | 2 ++ .../tree-select/nz-tree-select.component.html | 17 +++++++++++++- .../tree-select/nz-tree-select.component.ts | 13 +++++++++-- components/tree-select/nz-tree-select.spec.ts | 23 ++++++++++++++++++- 9 files changed, 65 insertions(+), 7 deletions(-) diff --git a/components/select/doc/index.en-US.md b/components/select/doc/index.en-US.md index 320cee08b2..10aab11fed 100644 --- a/components/select/doc/index.en-US.md +++ b/components/select/doc/index.en-US.md @@ -48,6 +48,8 @@ Select component to select value from options. | `[nzMenuItemSelectedIcon]` | The custom menuItemSelected icon | `TemplateRef` | - | | `[nzTokenSeparators]` | Separator used to tokenize on tag/multiple mode | `string[]` | `[]` | | `[nzLoading]` | indicate loading state | boolean | false | +| `[nzMaxTagCount]` | Max tag count to show| number | - | +| `[nzMaxTagPlaceholder]` | Placeholder for not showing tags | TemplateRef<{ $implicit: any[] }> | - | | `(ngModelChange)` | Current selected nz-option value change callback. | `EventEmitter` | - | | `(nzOpenChange)` | dropdown expand change callback | `EventEmitter` | `false` | | `(nzScrollToBottom)` | Called when dropdown scrolls to bottom | `EventEmitter` | - | diff --git a/components/select/doc/index.zh-CN.md b/components/select/doc/index.zh-CN.md index 76d2539a8a..c9524546ce 100644 --- a/components/select/doc/index.zh-CN.md +++ b/components/select/doc/index.zh-CN.md @@ -49,6 +49,8 @@ title: Select | `[nzMenuItemSelectedIcon]` | 自定义当前选中的条目图标 | `TemplateRef` | - | | `[nzTokenSeparators]` | 在 tags 和 multiple 模式下自动分词的分隔符 | `string[]` | `[]` | | `[nzLoading]` | 加载中状态 | boolean | `false` | +| `[nzMaxTagCount]` | 最多显示多少个 tag | number | - | +| `[nzMaxTagPlaceholder]` | 隐藏 tag 时显示的内容 | TemplateRef<{ $implicit: any[] }> | - | | `(ngModelChange)` | 选中的 nz-option 发生变化时,调用此函数 | `EventEmitter` | - | | `(nzOpenChange)` | 下拉菜单打开状态变化回调 | `EventEmitter` | - | | `(nzScrollToBottom)` | 下拉列表滚动到底部的回调 | `EventEmitter` | - | diff --git a/components/tree-select/demo/multiple.md b/components/tree-select/demo/multiple.md index 20fa00a62c..4db48f13bd 100755 --- a/components/tree-select/demo/multiple.md +++ b/components/tree-select/demo/multiple.md @@ -7,8 +7,8 @@ title: ## zh-CN -多选的树选择。 +多选的树选择,例子中通过 `nzMaxTagCount` 限制最多显示3个选项。 ## en-US -Multiple selection usage. +Multiple selection usage, max 3 option will display at the same time by `nzMaxTagCount`. diff --git a/components/tree-select/demo/multiple.ts b/components/tree-select/demo/multiple.ts index cf6a81c815..9582a31552 100755 --- a/components/tree-select/demo/multiple.ts +++ b/components/tree-select/demo/multiple.ts @@ -4,14 +4,19 @@ import { Component, OnInit } from '@angular/core'; selector: 'nz-demo-tree-select-multiple', template: ` + + and {{omittedValues.length}} more... + ` }) diff --git a/components/tree-select/doc/index.en-US.md b/components/tree-select/doc/index.en-US.md index e8a865e4fe..0d14d5dd98 100755 --- a/components/tree-select/doc/index.en-US.md +++ b/components/tree-select/doc/index.en-US.md @@ -34,4 +34,6 @@ Any data whose entries are defined in a hierarchical manner is fit to use this c | `[nzDefaultExpandAll]` | Whether to expand all treeNodes by default | `boolean` | `false` | | `[nzDefaultExpandedKeys]` | Default expanded treeNodes | `string[]` | - | | `[nzDisplayWith]` | How to display the selected node value in the trigger | `(node: NzTreeNode) => string` | `(node: NzTreeNode) => node.title` | +| `[nzMaxTagCount]` | Max tag count to show| number | - | +| `[nzMaxTagPlaceholder]` | Placeholder for not showing tags | TemplateRef<{ $implicit: NzTreeNode[] }> | - | | `(nzExpandChange)` | Callback function for when a treeNode is expanded or collapsed |`EventEmitter` | - | diff --git a/components/tree-select/doc/index.zh-CN.md b/components/tree-select/doc/index.zh-CN.md index 38235a80f0..9492bd2a82 100755 --- a/components/tree-select/doc/index.zh-CN.md +++ b/components/tree-select/doc/index.zh-CN.md @@ -34,4 +34,6 @@ title: TreeSelect | `[nzDefaultExpandAll]` | 默认展开所有树节点 | `boolean` | `false` | | `[nzDefaultExpandedKeys]` | 默认展开指定的树节点 | `string[]` | - | | `[nzDisplayWith]` | 如何在输入框显示所选的节点值的方法 | `(node: NzTreeNode) => string` | `(node: NzTreeNode) => node.title` | +| `[nzMaxTagCount]` | 最多显示多少个 tag | number | - | +| `[nzMaxTagPlaceholder]` | 隐藏 tag 时显示的内容 | TemplateRef<{ $implicit: NzTreeNode[] }> | - | | `(nzExpandChange)` | 点击展开树节点图标调用 | `EventEmitter` | - | diff --git a/components/tree-select/nz-tree-select.component.html b/components/tree-select/nz-tree-select.component.html index 8ed3a7d05a..9b55236e3c 100644 --- a/components/tree-select/nz-tree-select.component.html +++ b/components/tree-select/nz-tree-select.component.html @@ -101,7 +101,7 @@ class="ant-select-selection__placeholder"> {{ nzPlaceHolder }} - +
  • {{ nzDisplayWith(node) }}
  • +
  • +
    + + + + + + + {{ selectedNodes.length - nzMaxTagCount }} ... + +
    +
  • diff --git a/components/tree-select/nz-tree-select.component.ts b/components/tree-select/nz-tree-select.component.ts index d818e56a53..7165087e5e 100644 --- a/components/tree-select/nz-tree-select.component.ts +++ b/components/tree-select/nz-tree-select.component.ts @@ -17,6 +17,7 @@ import { Output, Renderer2, SimpleChanges, + TemplateRef, ViewChild } from '@angular/core'; import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; @@ -30,6 +31,7 @@ import { filter, tap } from 'rxjs/operators'; import { slideMotion } from '../core/animation/slide'; import { zoomMotion } from '../core/animation/zoom'; +import { NzSizeLDSType } from '../core/types/size'; import { InputBoolean } from '../core/util/convert'; import { NzFormatEmitEvent } from '../tree/interface'; import { NzTreeNode, NzTreeNodeOptions } from '../tree/nz-tree-node'; @@ -84,11 +86,13 @@ export class NzTreeSelectComponent implements ControlValueAccessor, OnInit, OnDe @Input() nzNotFoundContent: string; @Input() nzNodes: Array = []; @Input() nzOpen = false; - @Input() nzSize = 'default'; + @Input() nzSize: NzSizeLDSType = 'default'; @Input() nzPlaceHolder = ''; @Input() nzDropdownStyle: { [ key: string ]: string; }; @Input() nzDefaultExpandedKeys: string[] = []; @Input() nzDisplayWith: (node: NzTreeNode) => string = (node: NzTreeNode) => node.title; + @Input() nzMaxTagCount: number; + @Input() nzMaxTagPlaceholder: TemplateRef<{ $implicit: NzTreeNode[] }>; @Output() readonly nzOpenChange = new EventEmitter(); @Output() readonly nzCleared = new EventEmitter(); @Output() readonly nzRemoved = new EventEmitter(); @@ -240,7 +244,12 @@ export class NzTreeSelectComponent implements ControlValueAccessor, OnInit, OnDe ) { e.preventDefault(); if (this.selectedNodes.length) { - this.removeSelected(this.selectedNodes[ this.selectedNodes.length - 1 ]); + const removeNode = this.selectedNodes[ this.selectedNodes.length - 1 ]; + this.removeSelected(removeNode); + this.nzTreeService.$statusChange.next({ + 'eventName': 'removeSelect', + 'node' : removeNode + }); } } } diff --git a/components/tree-select/nz-tree-select.spec.ts b/components/tree-select/nz-tree-select.spec.ts index a3235c9a81..79a7c97240 100644 --- a/components/tree-select/nz-tree-select.spec.ts +++ b/components/tree-select/nz-tree-select.spec.ts @@ -217,6 +217,23 @@ describe('tree-select component', () => { expect(selectedValueEl.style.display).toBe('none'); expect(selectedValueEl.style.opacity).toBe('1'); })); + it('should max tag count work', fakeAsync(() => { + testComponent.multiple = true; + testComponent.value = [ '1001', '10001', '100011', '100012' ]; + fixture.detectChanges(); + tick(200); + fixture.detectChanges(); + expect(treeSelect.nativeElement.querySelectorAll('.ant-select-selection__choice').length).toBe(4); + testComponent.maxTagCount = 2; + fixture.detectChanges(); + tick(200); + fixture.detectChanges(); + expect(treeSelect.nativeElement.querySelectorAll('.ant-select-selection__choice').length).toBe(3); + const maxTagPlaceholderElement = treeSelect.nativeElement.querySelectorAll('.ant-select-selection__choice')[2] + .querySelector('.ant-select-selection__choice__content'); + expect(maxTagPlaceholderElement).toBeTruthy(); + expect(maxTagPlaceholderElement.innerText.trim()).toBe(`+ ${testComponent.value.length - testComponent.maxTagCount} ...`); + })); }); describe('checkable', () => { @@ -450,6 +467,8 @@ describe('tree-select component', () => { [nzDropdownMatchSelectWidth]="dropdownMatchSelectWidth" [nzDisabled]="disabled" [nzShowSearch]="showSearch" + [nzMultiple]="multiple" + [nzMaxTagCount]="maxTagCount" [nzDropdownStyle]="{ 'height': '120px' }"> ` @@ -457,12 +476,14 @@ describe('tree-select component', () => { export class NzTestTreeSelectBasicComponent { @ViewChild(NzTreeSelectComponent) nzSelectTreeComponent: NzTreeSelectComponent; expandKeys = [ '1001', '10001' ]; - value = '10001'; + value: string | string[] = '10001'; size = 'default'; allowClear = false; disabled = false; showSearch = false; dropdownMatchSelectWidth = true; + multiple = false; + maxTagCount = Infinity; nodes = [ new NzTreeNode({ title : 'root1',