55
66import {
77 AfterViewInit ,
8+ ChangeDetectorRef ,
89 Directive ,
910 ElementRef ,
1011 EventEmitter ,
1112 ExistingProvider ,
1213 forwardRef ,
13- OnDestroy
14+ NgZone ,
15+ OnDestroy ,
16+ Output
1417} from '@angular/core' ;
1518import { ControlValueAccessor , NG_VALUE_ACCESSOR } from '@angular/forms' ;
19+ import { fromEvent } from 'rxjs' ;
20+ import { takeUntil } from 'rxjs/operators' ;
1621
22+ import { NzDestroyService } from 'ng-zorro-antd/core/services' ;
1723import { OnChangeType , OnTouchedType } from 'ng-zorro-antd/core/types' ;
1824
1925import { NZ_MENTION_CONFIG } from './config' ;
@@ -29,28 +35,34 @@ export const NZ_MENTION_TRIGGER_ACCESSOR: ExistingProvider = {
2935@Directive ( {
3036 selector : 'input[nzMentionTrigger], textarea[nzMentionTrigger]' ,
3137 exportAs : 'nzMentionTrigger' ,
32- providers : [ NZ_MENTION_TRIGGER_ACCESSOR ] ,
38+ providers : [ NzDestroyService , NZ_MENTION_TRIGGER_ACCESSOR ] ,
3339 host : {
34- autocomplete : 'off' ,
35- '(focusin)' : 'onFocusin.emit()' ,
36- '(blur)' : 'onBlur.emit()' ,
37- '(input)' : 'onInput.emit($event)' ,
38- '(keydown)' : 'onKeydown.emit($event)' ,
39- '(click)' : 'onClick.emit($event)'
40+ autocomplete : 'off'
4041 }
4142} )
4243export class NzMentionTriggerDirective implements ControlValueAccessor , OnDestroy , AfterViewInit {
4344 onChange : OnChangeType = ( ) => { } ;
4445 onTouched : OnTouchedType = ( ) => { } ;
4546
46- readonly onFocusin : EventEmitter < void > = new EventEmitter ( ) ;
47- readonly onBlur : EventEmitter < void > = new EventEmitter ( ) ;
48- readonly onInput : EventEmitter < KeyboardEvent > = new EventEmitter ( ) ;
49- readonly onKeydown : EventEmitter < KeyboardEvent > = new EventEmitter ( ) ;
50- readonly onClick : EventEmitter < MouseEvent > = new EventEmitter ( ) ;
47+ // eslint-disable-next-line @angular-eslint/no-output-on-prefix
48+ @Output ( ) readonly onFocusin : EventEmitter < void > = new EventEmitter ( ) ;
49+ // eslint-disable-next-line @angular-eslint/no-output-on-prefix
50+ @Output ( ) readonly onBlur : EventEmitter < void > = new EventEmitter ( ) ;
51+ // eslint-disable-next-line @angular-eslint/no-output-on-prefix
52+ @Output ( ) readonly onInput : EventEmitter < KeyboardEvent > = new EventEmitter ( ) ;
53+ // eslint-disable-next-line @angular-eslint/no-output-on-prefix
54+ @Output ( ) readonly onKeydown : EventEmitter < KeyboardEvent > = new EventEmitter ( ) ;
55+ // eslint-disable-next-line @angular-eslint/no-output-on-prefix
56+ @Output ( ) readonly onClick : EventEmitter < MouseEvent > = new EventEmitter ( ) ;
5157 value ?: string ;
5258
53- constructor ( public el : ElementRef , private nzMentionService : NzMentionService ) { }
59+ constructor (
60+ public el : ElementRef < HTMLInputElement | HTMLTextAreaElement > ,
61+ private ngZone : NgZone ,
62+ private ref : ChangeDetectorRef ,
63+ private destroy$ : NzDestroyService ,
64+ private nzMentionService : NzMentionService
65+ ) { }
5466
5567 completeEvents ( ) : void {
5668 this . onFocusin . complete ( ) ;
@@ -60,7 +72,7 @@ export class NzMentionTriggerDirective implements ControlValueAccessor, OnDestro
6072 this . onClick . complete ( ) ;
6173 }
6274
63- focus ( caretPos ? : number ) : void {
75+ focus ( caretPos : number | null = null ) : void {
6476 this . el . nativeElement . focus ( ) ;
6577 this . el . nativeElement . setSelectionRange ( caretPos , caretPos ) ;
6678 }
@@ -98,9 +110,30 @@ export class NzMentionTriggerDirective implements ControlValueAccessor, OnDestro
98110
99111 ngAfterViewInit ( ) : void {
100112 this . nzMentionService . registerTrigger ( this ) ;
113+
114+ this . setupEventListener ( 'blur' , this . onBlur ) ;
115+ this . setupEventListener ( 'focusin' , this . onFocusin ) ;
116+ this . setupEventListener ( 'input' , this . onInput , true ) ;
117+ this . setupEventListener ( 'click' , this . onClick , true ) ;
118+ this . setupEventListener ( 'keydown' , this . onKeydown , true ) ;
101119 }
102120
103121 ngOnDestroy ( ) : void {
104122 this . completeEvents ( ) ;
105123 }
124+
125+ private setupEventListener < T > ( eventName : string , eventEmitter : EventEmitter < T > , shouldPassEvent = false ) : void {
126+ this . ngZone . runOutsideAngular ( ( ) => {
127+ fromEvent < T > ( this . el . nativeElement , eventName )
128+ . pipe ( takeUntil ( this . destroy$ ) )
129+ . subscribe ( event => {
130+ if ( eventEmitter . observers . length ) {
131+ this . ngZone . run ( ( ) => {
132+ eventEmitter . emit ( shouldPassEvent ? event : undefined ) ;
133+ this . ref . markForCheck ( ) ;
134+ } ) ;
135+ }
136+ } ) ;
137+ } ) ;
138+ }
106139}
0 commit comments