@@ -19,6 +19,7 @@ import {
19
19
forwardRef ,
20
20
Host ,
21
21
Input ,
22
+ NgZone ,
22
23
OnChanges ,
23
24
OnDestroy ,
24
25
OnInit ,
@@ -31,7 +32,7 @@ import {
31
32
ViewEncapsulation
32
33
} from '@angular/core' ;
33
34
import { ControlValueAccessor , NG_VALUE_ACCESSOR } from '@angular/forms' ;
34
- import { BehaviorSubject , combineLatest , merge } from 'rxjs' ;
35
+ import { BehaviorSubject , combineLatest , fromEvent , merge } from 'rxjs' ;
35
36
import { startWith , switchMap , takeUntil } from 'rxjs/operators' ;
36
37
37
38
import { slideMotion } from 'ng-zorro-antd/core/animation' ;
@@ -119,7 +120,6 @@ export type NzSelectSizeType = 'large' | 'default' | 'small';
119
120
[cdkConnectedOverlayTransformOriginOn]="'.ant-select-dropdown'"
120
121
[cdkConnectedOverlayPanelClass]="nzDropdownClassName!"
121
122
[cdkConnectedOverlayOpen]="nzOpen"
122
- (overlayKeydown)="onOverlayKeyDown($event)"
123
123
(overlayOutsideClick)="onClickOutside($event)"
124
124
(detach)="setOpenState(false)"
125
125
(positionChange)="onPositionChange($event)"
@@ -161,8 +161,7 @@ export type NzSelectSizeType = 'large' | 'default' | 'small';
161
161
'[class.ant-select-focused]' : 'nzOpen || focused' ,
162
162
'[class.ant-select-single]' : `nzMode === 'default'` ,
163
163
'[class.ant-select-multiple]' : `nzMode !== 'default'` ,
164
- '[class.ant-select-rtl]' : `dir === 'rtl'` ,
165
- '(click)' : 'onHostClick()'
164
+ '[class.ant-select-rtl]' : `dir === 'rtl'`
166
165
}
167
166
} )
168
167
export class NzSelectComponent implements ControlValueAccessor , OnInit , AfterContentInit , OnChanges , OnDestroy {
@@ -292,14 +291,6 @@ export class NzSelectComponent implements ControlValueAccessor, OnInit, AfterCon
292
291
this . clearInput ( ) ;
293
292
}
294
293
295
- onHostClick ( ) : void {
296
- if ( ( this . nzOpen && this . nzShowSearch ) || this . nzDisabled ) {
297
- return ;
298
- }
299
-
300
- this . setOpenState ( ! this . nzOpen ) ;
301
- }
302
-
303
294
updateListOfContainerItem ( ) : void {
304
295
let listOfContainerItem = this . listOfTagAndTemplateItem
305
296
. filter ( item => ! item . nzHide )
@@ -384,12 +375,6 @@ export class NzSelectComponent implements ControlValueAccessor, OnInit, AfterCon
384
375
this . clearInput ( ) ;
385
376
}
386
377
387
- onOverlayKeyDown ( e : KeyboardEvent ) : void {
388
- if ( e . keyCode === ESCAPE ) {
389
- this . setOpenState ( false ) ;
390
- }
391
- }
392
-
393
378
onKeyDown ( e : KeyboardEvent ) : void {
394
379
if ( this . nzDisabled ) {
395
380
return ;
@@ -474,7 +459,7 @@ export class NzSelectComponent implements ControlValueAccessor, OnInit, AfterCon
474
459
}
475
460
476
461
onClickOutside ( event : MouseEvent ) : void {
477
- if ( ! this . elementRef . nativeElement . contains ( event . target ) ) {
462
+ if ( ! this . host . nativeElement . contains ( event . target as HTMLElement ) ) {
478
463
this . setOpenState ( false ) ;
479
464
}
480
465
}
@@ -516,10 +501,11 @@ export class NzSelectComponent implements ControlValueAccessor, OnInit, AfterCon
516
501
}
517
502
518
503
constructor (
504
+ private ngZone : NgZone ,
519
505
private destroy$ : NzDestroyService ,
520
506
public nzConfigService : NzConfigService ,
521
507
private cdr : ChangeDetectorRef ,
522
- private elementRef : ElementRef ,
508
+ private host : ElementRef < HTMLElement > ,
523
509
private platform : Platform ,
524
510
private focusMonitor : FocusMonitor ,
525
511
@Optional ( ) private directionality : Directionality ,
@@ -592,7 +578,7 @@ export class NzSelectComponent implements ControlValueAccessor, OnInit, AfterCon
592
578
593
579
ngOnInit ( ) : void {
594
580
this . focusMonitor
595
- . monitor ( this . elementRef , true )
581
+ . monitor ( this . host , true )
596
582
. pipe ( takeUntil ( this . destroy$ ) )
597
583
. subscribe ( focusOrigin => {
598
584
if ( ! focusOrigin ) {
@@ -640,6 +626,29 @@ export class NzSelectComponent implements ControlValueAccessor, OnInit, AfterCon
640
626
} ) ;
641
627
642
628
this . dir = this . directionality . value ;
629
+
630
+ this . ngZone . runOutsideAngular ( ( ) =>
631
+ fromEvent ( this . host . nativeElement , 'click' )
632
+ . pipe ( takeUntil ( this . destroy$ ) )
633
+ . subscribe ( ( ) => {
634
+ if ( ( this . nzOpen && this . nzShowSearch ) || this . nzDisabled ) {
635
+ return ;
636
+ }
637
+
638
+ this . ngZone . run ( ( ) => this . setOpenState ( ! this . nzOpen ) ) ;
639
+ } )
640
+ ) ;
641
+
642
+ // Caretaker note: we could've added this listener within the template `(overlayKeydown)="..."`,
643
+ // but with this approach, it'll run change detection on each keyboard click, and also it'll run
644
+ // `markForCheck()` internally, which means the whole component tree (starting from the root and
645
+ // going down to the select component) will be re-checked and updated (if needed).
646
+ // This is safe to do that manually since `setOpenState()` calls `markForCheck()` if needed.
647
+ this . cdkConnectedOverlay . overlayKeydown . pipe ( takeUntil ( this . destroy$ ) ) . subscribe ( event => {
648
+ if ( event . keyCode === ESCAPE ) {
649
+ this . setOpenState ( false ) ;
650
+ }
651
+ } ) ;
643
652
}
644
653
645
654
ngAfterContentInit ( ) : void {
@@ -679,8 +688,9 @@ export class NzSelectComponent implements ControlValueAccessor, OnInit, AfterCon
679
688
} ) ;
680
689
}
681
690
}
691
+
682
692
ngOnDestroy ( ) : void {
683
693
cancelRequestAnimationFrame ( this . requestId ) ;
684
- this . focusMonitor . stopMonitoring ( this . elementRef ) ;
694
+ this . focusMonitor . stopMonitoring ( this . host ) ;
685
695
}
686
696
}
0 commit comments