5
5
6
6
import { Direction , Directionality } from '@angular/cdk/bidi' ;
7
7
import { BACKSPACE , DOWN_ARROW , ENTER , ESCAPE , LEFT_ARROW , RIGHT_ARROW , UP_ARROW } from '@angular/cdk/keycodes' ;
8
- import { CdkConnectedOverlay , ConnectionPositionPair , OverlayModule } from '@angular/cdk/overlay' ;
8
+ import {
9
+ CdkConnectedOverlay ,
10
+ ConnectedOverlayPositionChange ,
11
+ ConnectionPositionPair ,
12
+ OverlayModule
13
+ } from '@angular/cdk/overlay' ;
9
14
import { _getEventTarget } from '@angular/cdk/platform' ;
10
15
import { SlicePipe } from '@angular/common' ;
11
16
import {
@@ -43,7 +48,13 @@ import { slideMotion } from 'ng-zorro-antd/core/animation';
43
48
import { NzConfigKey , NzConfigService , WithConfig } from 'ng-zorro-antd/core/config' ;
44
49
import { NzFormItemFeedbackIconComponent , NzFormNoStatusService , NzFormStatusService } from 'ng-zorro-antd/core/form' ;
45
50
import { NzNoAnimationDirective } from 'ng-zorro-antd/core/no-animation' ;
46
- import { DEFAULT_CASCADER_POSITIONS , NzOverlayModule } from 'ng-zorro-antd/core/overlay' ;
51
+ import {
52
+ DEFAULT_CASCADER_POSITIONS ,
53
+ getPlacementName ,
54
+ NzOverlayModule ,
55
+ POSITION_MAP ,
56
+ POSITION_TYPE
57
+ } from 'ng-zorro-antd/core/overlay' ;
47
58
import { NzDestroyService } from 'ng-zorro-antd/core/services' ;
48
59
import { NzTreeBase , NzTreeNode } from 'ng-zorro-antd/core/tree' ;
49
60
import {
@@ -62,6 +73,7 @@ import {
62
73
NzSelectClearComponent ,
63
74
NzSelectItemComponent ,
64
75
NzSelectPlaceholderComponent ,
76
+ NzSelectPlacementType ,
65
77
NzSelectSearchComponent
66
78
} from 'ng-zorro-antd/select' ;
67
79
import { NZ_SPACE_COMPACT_ITEM_TYPE , NZ_SPACE_COMPACT_SIZE , NzSpaceCompactItemDirective } from 'ng-zorro-antd/space' ;
@@ -73,6 +85,7 @@ import {
73
85
NzCascaderComponentAsSource ,
74
86
NzCascaderExpandTrigger ,
75
87
NzCascaderOption ,
88
+ NzCascaderPlacement ,
76
89
NzCascaderSize ,
77
90
NzCascaderTriggerType ,
78
91
NzShowSearchOptions
@@ -166,9 +179,14 @@ const defaultDisplayRender = (labels: string[]): string => labels.join(' / ');
166
179
[cdkConnectedOverlayOpen]="menuVisible"
167
180
(overlayOutsideClick)="onClickOutside($event)"
168
181
(detach)="closeMenu()"
182
+ (positionChange)="onPositionChange($event)"
169
183
>
170
184
<div
171
- class="ant-select-dropdown ant-cascader-dropdown ant-select-dropdown-placement-bottomLeft"
185
+ class="ant-select-dropdown ant-cascader-dropdown"
186
+ [class.ant-select-dropdown-placement-bottomLeft]="dropdownPosition === 'bottomLeft'"
187
+ [class.ant-select-dropdown-placement-bottomRight]="dropdownPosition === 'bottomRight'"
188
+ [class.ant-select-dropdown-placement-topLeft]="dropdownPosition === 'topLeft'"
189
+ [class.ant-select-dropdown-placement-topRight]="dropdownPosition === 'topRight'"
172
190
[class.ant-cascader-dropdown-rtl]="dir === 'rtl'"
173
191
[@slideMotion]="'enter'"
174
192
[@.disabled]="!!noAnimation?.nzNoAnimation"
@@ -285,9 +303,11 @@ export class NzCascaderComponent
285
303
set input ( inputComponent : NzSelectSearchComponent | undefined ) {
286
304
this . input$ . next ( inputComponent ?. inputElement ) ;
287
305
}
306
+
288
307
get input ( ) : ElementRef < HTMLInputElement > | undefined {
289
308
return this . input$ . getValue ( ) ;
290
309
}
310
+
291
311
/** Used to store the native `<input type="search" />` element since it might be set asynchronously. */
292
312
private input$ = new BehaviorSubject < ElementRef < HTMLInputElement > | undefined > ( undefined ) ;
293
313
@@ -327,6 +347,7 @@ export class NzCascaderComponent
327
347
@Input ( ) nzStatus : NzStatus = '' ;
328
348
@Input ( { transform : booleanAttribute } ) nzMultiple : boolean = false ;
329
349
@Input ( ) nzMaxTagCount : number = Infinity ;
350
+ @Input ( ) nzPlacement : NzCascaderPlacement = 'bottomLeft' ;
330
351
331
352
@Input ( ) nzTriggerAction : NzCascaderTriggerType | NzCascaderTriggerType [ ] = [ 'click' ] as NzCascaderTriggerType [ ] ;
332
353
@Input ( ) nzChangeOn ?: ( option : NzCascaderOption , level : number ) => boolean ;
@@ -389,6 +410,7 @@ export class NzCascaderComponent
389
410
*/
390
411
dropdownWidthStyle ?: string ;
391
412
dropdownHeightStyle : 'auto' | '' = '' ;
413
+ dropdownPosition : NzCascaderPlacement = 'bottomLeft' ;
392
414
isFocused = false ;
393
415
394
416
locale ! : NzCascaderI18nInterface ;
@@ -551,13 +573,23 @@ export class NzCascaderComponent
551
573
}
552
574
553
575
ngOnChanges ( changes : SimpleChanges ) : void {
554
- const { nzStatus, nzSize } = changes ;
576
+ const { nzStatus, nzSize, nzPlacement } = changes ;
555
577
if ( nzStatus ) {
556
578
this . setStatusStyles ( this . nzStatus , this . hasFeedback ) ;
557
579
}
558
580
if ( nzSize ) {
559
581
this . size . set ( nzSize . currentValue ) ;
560
582
}
583
+ if ( nzPlacement ) {
584
+ const { currentValue } = nzPlacement ;
585
+ this . dropdownPosition = currentValue as NzCascaderPlacement ;
586
+ const listOfPlacement = [ 'bottomLeft' , 'topLeft' , 'bottomRight' , 'topRight' ] ;
587
+ if ( currentValue && listOfPlacement . includes ( currentValue ) ) {
588
+ this . positions = [ POSITION_MAP [ currentValue as POSITION_TYPE ] ] ;
589
+ } else {
590
+ this . positions = listOfPlacement . map ( e => POSITION_MAP [ e as POSITION_TYPE ] ) ;
591
+ }
592
+ }
561
593
}
562
594
563
595
ngOnDestroy ( ) : void {
@@ -939,6 +971,11 @@ export class NzCascaderComponent
939
971
}
940
972
}
941
973
974
+ onPositionChange ( position : ConnectedOverlayPositionChange ) : void {
975
+ const placement = getPlacementName ( position ) ;
976
+ this . dropdownPosition = placement as NzSelectPlacementType ;
977
+ }
978
+
942
979
private isActionTrigger ( action : 'click' | 'hover' ) : boolean {
943
980
return typeof this . nzTriggerAction === 'string'
944
981
? this . nzTriggerAction === action
0 commit comments