diff --git a/components/tree-select/demo/module b/components/tree-select/demo/module index 9e31c4d770..e8d87a9b9f 100644 --- a/components/tree-select/demo/module +++ b/components/tree-select/demo/module @@ -1,7 +1,8 @@ import { NzTreeSelectModule } from 'ng-zorro-antd/tree-select'; import { NzIconModule } from 'ng-zorro-antd/icon'; import { FormsModule } from '@angular/forms'; +import { NzRadioModule } from 'ng-zorro-antd/radio'; import { NzSpaceModule } from 'ng-zorro-antd/space'; -export const moduleList = [ FormsModule, NzTreeSelectModule, NzIconModule , NzSpaceModule]; +export const moduleList = [ FormsModule, NzTreeSelectModule, NzIconModule , NzRadioModule , NzSpaceModule]; diff --git a/components/tree-select/demo/placement.md b/components/tree-select/demo/placement.md new file mode 100644 index 0000000000..d465456bf9 --- /dev/null +++ b/components/tree-select/demo/placement.md @@ -0,0 +1,13 @@ +--- +order: 7 +title: + zh-CN: 位置 + en-US: Placement +--- + +## zh-CN + +可以通过 `nzPlacement` 手动指定弹出的位置。 +## en-US + +You can manually specify the position of the popup via `nzPlacement`. diff --git a/components/tree-select/demo/placement.ts b/components/tree-select/demo/placement.ts new file mode 100644 index 0000000000..6e941ac537 --- /dev/null +++ b/components/tree-select/demo/placement.ts @@ -0,0 +1,59 @@ +import { Component } from '@angular/core'; +export type NzPlacementType = 'bottomLeft' | 'bottomRight' | 'topLeft' | 'topRight' | ''; + +@Component({ + selector: 'nz-demo-tree-select-placement', + template: ` + + + + + + and {{ omittedValues.length }} more... + + ` +}) +export class NzDemoTreeSelectPlacementComponent { + list: NzPlacementType[] = ['topLeft', 'topRight', 'bottomLeft', 'bottomRight']; + placement: NzPlacementType = 'topLeft'; + value: string[] = []; + nodes = [ + { + title: 'parent 1', + key: '100', + children: [ + { + title: 'parent 1-0', + key: '1001', + children: [ + { title: 'leaf 1-0-0', key: '10010', isLeaf: true }, + { title: 'leaf 1-0-1', key: '10011', isLeaf: true } + ] + }, + { + title: 'parent 1-1', + key: '1002', + children: [{ title: 'leaf 1-1-0', key: '10020', isLeaf: true }] + } + ] + } + ]; + + onChange($event: string[]): void { + console.log($event); + } +} diff --git a/components/tree-select/doc/index.en-US.md b/components/tree-select/doc/index.en-US.md index 3ed2ee1f15..c2d3c533ac 100755 --- a/components/tree-select/doc/index.en-US.md +++ b/components/tree-select/doc/index.en-US.md @@ -25,6 +25,7 @@ import { NzTreeSelectModule } from 'ng-zorro-antd/tree-select'; | `[nzId]` | input id attribute inside the component| `string` | - | | `[nzAllowClear]` | Whether allow clear | `boolean` | `false` | | `[nzPlaceHolder]` | Placeholder of the select input | `string` | - | +| `[nzPlacement]` | The position where the selection box pops up | `bottomLeft` `bottomRight` `topLeft` `topRight` | bottomLeft | | `[nzDisabled]` | Disabled or not | `boolean` | `false` | | `[nzShowIcon]` | Shows the icon before a TreeNode's title. There is no default style | `boolean` | `false` | | `[nzShowSearch]` | Whether to display a search input in the dropdown menu(valid only in the single mode) | `boolean` | `false` | ✅ | diff --git a/components/tree-select/doc/index.zh-CN.md b/components/tree-select/doc/index.zh-CN.md index b7000b3e34..4550859bc9 100755 --- a/components/tree-select/doc/index.zh-CN.md +++ b/components/tree-select/doc/index.zh-CN.md @@ -25,6 +25,7 @@ import { NzTreeSelectModule } from 'ng-zorro-antd/tree-select'; | `[nzId]` | 组件内部 input 的 id 值 | `string` | - | | `[nzAllowClear]` | 显示清除按钮 | `boolean` | `false` | | `[nzPlaceHolder]` | 选择框默认文字 | `string` | - | +| `[nzPlacement]` | 选择框弹出的位置 | `bottomLeft` `bottomRight` `topLeft` `topRight` | bottomLeft | | `[nzDisabled]` | 禁用选择器 | `boolean` | `false` | | `[nzShowIcon]` | 是否展示 TreeNode title 前的图标,没有默认样式 | `boolean` | `false` | ✅ | | `[nzShowSearch]` | 显示搜索框 | `boolean` | `false` | diff --git a/components/tree-select/tree-select.component.ts b/components/tree-select/tree-select.component.ts index 1f2603e9fc..ecc430c4f1 100644 --- a/components/tree-select/tree-select.component.ts +++ b/components/tree-select/tree-select.component.ts @@ -6,7 +6,12 @@ import { FocusMonitor } from '@angular/cdk/a11y'; import { Direction, Directionality } from '@angular/cdk/bidi'; import { BACKSPACE, ESCAPE, TAB } from '@angular/cdk/keycodes'; -import { CdkConnectedOverlay, CdkOverlayOrigin, ConnectedOverlayPositionChange } from '@angular/cdk/overlay'; +import { + CdkConnectedOverlay, + CdkOverlayOrigin, + ConnectedOverlayPositionChange, + ConnectionPositionPair +} from '@angular/cdk/overlay'; import { ChangeDetectorRef, Component, @@ -36,6 +41,7 @@ import { slideMotion } from 'ng-zorro-antd/core/animation'; import { NzConfigKey, NzConfigService, WithConfig } from 'ng-zorro-antd/core/config'; import { NzFormNoStatusService, NzFormStatusService } from 'ng-zorro-antd/core/form'; import { NzNoAnimationDirective } from 'ng-zorro-antd/core/no-animation'; +import { POSITION_MAP } from 'ng-zorro-antd/core/overlay'; import { reqAnimFrame } from 'ng-zorro-antd/core/polyfill'; import { NzFormatEmitEvent, @@ -65,8 +71,15 @@ export function higherOrderServiceFactory(injector: Injector): NzTreeBaseService return injector.get(NzTreeSelectService); } +export type NzPlacementType = 'bottomLeft' | 'bottomRight' | 'topLeft' | 'topRight' | ''; const NZ_CONFIG_MODULE_NAME: NzConfigKey = 'treeSelect'; const TREE_SELECT_DEFAULT_CLASS = 'ant-select-dropdown ant-select-tree-dropdown'; +const listOfPositions = [ + POSITION_MAP.bottomLeft, + POSITION_MAP.bottomRight, + POSITION_MAP.topRight, + POSITION_MAP.topLeft +]; @Component({ selector: 'nz-tree-select', @@ -78,6 +91,7 @@ const TREE_SELECT_DEFAULT_CLASS = 'ant-select-dropdown ant-select-tree-dropdown' nzConnectedOverlay [cdkConnectedOverlayHasBackdrop]="nzBackdrop" [cdkConnectedOverlayOrigin]="cdkOverlayOrigin" + [cdkConnectedOverlayPositions]="nzPlacement ? positions : []" [cdkConnectedOverlayOpen]="nzOpen" [cdkConnectedOverlayTransformOriginOn]="'.ant-select-tree-dropdown'" [cdkConnectedOverlayMinWidth]="$any(nzDropdownMatchSelectWidth ? null : triggerWidth)" @@ -273,6 +287,7 @@ export class NzTreeSelectComponent extends NzTreeBase implements ControlValueAcc @Input() nzDropdownClassName?: string; @Input() @WithConfig() nzBackdrop = false; @Input() nzStatus: NzStatus = ''; + @Input() nzPlacement: NzPlacementType = ''; @Input() set nzExpandedKeys(value: string[]) { this.expandedKeys = value; @@ -322,6 +337,7 @@ export class NzTreeSelectComponent extends NzTreeBase implements ControlValueAcc expandedKeys: string[] = []; value: string[] = []; dir: Direction = 'ltr'; + positions: ConnectionPositionPair[] = []; private destroy$ = new Subject(); @@ -427,7 +443,7 @@ export class NzTreeSelectComponent extends NzTreeBase implements ControlValueAcc } ngOnChanges(changes: SimpleChanges): void { - const { nzNodes, nzDropdownClassName, nzStatus } = changes; + const { nzNodes, nzDropdownClassName, nzStatus, nzPlacement } = changes; if (nzNodes) { this.updateSelectedNodes(true); } @@ -438,6 +454,12 @@ export class NzTreeSelectComponent extends NzTreeBase implements ControlValueAcc if (nzStatus) { this.setStatusStyles(this.nzStatus, this.hasFeedback); } + + if (nzPlacement && this.nzPlacement) { + if (POSITION_MAP[this.nzPlacement]) { + this.positions = [POSITION_MAP[this.nzPlacement]]; + } + } } writeValue(value: string[] | string): void { @@ -647,7 +669,9 @@ export class NzTreeSelectComponent extends NzTreeBase implements ControlValueAcc } updateCdkConnectedOverlayStatus(): void { - this.triggerWidth = this.cdkOverlayOrigin.elementRef.nativeElement.getBoundingClientRect().width; + if (!this.nzPlacement || !listOfPositions.includes(POSITION_MAP[this.nzPlacement])) { + this.triggerWidth = this.cdkOverlayOrigin.elementRef.nativeElement.getBoundingClientRect().width; + } } trackValue(_index: number, option: NzTreeNode): string {