7
7
Inject ,
8
8
Input ,
9
9
OnChanges ,
10
+ OnDestroy ,
10
11
OnInit ,
11
12
Optional ,
12
13
Output ,
@@ -19,6 +20,7 @@ import {
19
20
CodeInputComponentConfigToken ,
20
21
defaultComponentConfig
21
22
} from './code-input.component.config' ;
23
+ import { Subscription } from 'rxjs' ;
22
24
23
25
enum InputState {
24
26
ready = 0 ,
@@ -31,7 +33,7 @@ enum InputState {
31
33
templateUrl : 'code-input.component.html' ,
32
34
styleUrls : [ './code-input.component.scss' ]
33
35
} )
34
- export class CodeInputComponent implements AfterViewInit , OnInit , OnChanges , AfterViewChecked , CodeInputComponentConfig {
36
+ export class CodeInputComponent implements AfterViewInit , OnInit , OnChanges , OnDestroy , AfterViewChecked , CodeInputComponentConfig {
35
37
36
38
@ViewChildren ( 'input' ) inputsList ! : QueryList < ElementRef > ;
37
39
@@ -51,10 +53,11 @@ export class CodeInputComponent implements AfterViewInit, OnInit, OnChanges, Aft
51
53
@Output ( ) readonly codeChanged = new EventEmitter < string > ( ) ;
52
54
@Output ( ) readonly codeCompleted = new EventEmitter < string > ( ) ;
53
55
54
- public placeholders ! : number [ ] ;
56
+ public placeholders : number [ ] = [ ] ;
55
57
56
58
private inputs : HTMLInputElement [ ] = [ ] ;
57
59
private inputsStates : InputState [ ] = [ ] ;
60
+ private inputsListSubscription ! : Subscription ;
58
61
59
62
// tslint:disable-next-line:variable-name
60
63
private _codeLength ! : number ;
@@ -90,20 +93,16 @@ export class CodeInputComponent implements AfterViewInit, OnInit, OnChanges, Aft
90
93
*/
91
94
92
95
ngOnInit ( ) : void {
93
- // defining internal code length prop for skipping external prop updates
94
- this . _codeLength = this . codeLength ;
95
- this . placeholders = Array ( this . _codeLength ) . fill ( 1 ) ;
96
+ // defining the state
96
97
this . state . isInitialFocusFieldEnabled = ! this . isEmpty ( this . initialFocusField ) ;
98
+ // initiating the code
99
+ this . onCodeLengthChanges ( ) ;
97
100
}
98
101
99
102
ngAfterViewInit ( ) : void {
100
- this . inputsList . forEach ( ( item ) => {
101
- this . inputs . push ( item . nativeElement ) ;
102
- this . inputsStates . push ( InputState . ready ) ;
103
- } ) ;
104
-
105
- // the @Input code might have value. Checking
106
- this . onInputCodeChanges ( ) ;
103
+ // initiation of the inputs
104
+ this . inputsListSubscription = this . inputsList . changes . subscribe ( this . onInputsListChanges . bind ( this ) ) ;
105
+ this . onInputsListChanges ( this . inputsList ) ;
107
106
}
108
107
109
108
ngAfterViewChecked ( ) : void {
@@ -114,6 +113,15 @@ export class CodeInputComponent implements AfterViewInit, OnInit, OnChanges, Aft
114
113
if ( changes . code ) {
115
114
this . onInputCodeChanges ( ) ;
116
115
}
116
+ if ( changes . codeLength ) {
117
+ this . onCodeLengthChanges ( ) ;
118
+ }
119
+ }
120
+
121
+ ngOnDestroy ( ) : void {
122
+ if ( this . inputsListSubscription ) {
123
+ this . inputsListSubscription . unsubscribe ( ) ;
124
+ }
117
125
}
118
126
119
127
/**
@@ -297,6 +305,37 @@ export class CodeInputComponent implements AfterViewInit, OnInit, OnChanges, Aft
297
305
} ) ;
298
306
}
299
307
308
+ private onCodeLengthChanges ( ) : void {
309
+ if ( ! this . codeLength ) {
310
+ return ;
311
+ }
312
+
313
+ this . _codeLength = this . codeLength ;
314
+ if ( this . _codeLength > this . placeholders . length ) {
315
+ const numbers = Array ( this . _codeLength - this . placeholders . length ) . fill ( 1 ) ;
316
+ this . placeholders . splice ( this . placeholders . length - 1 , 0 , ...numbers ) ;
317
+ }
318
+ else if ( this . _codeLength < this . placeholders . length ) {
319
+ this . placeholders . splice ( this . _codeLength ) ;
320
+ }
321
+ }
322
+
323
+ private onInputsListChanges ( list : QueryList < ElementRef > ) : void {
324
+ if ( list . length > this . inputs . length ) {
325
+ const inputsToAdd = list . filter ( ( item , index ) => index > this . inputs . length - 1 ) ;
326
+ this . inputs . splice ( this . inputs . length , 0 , ...inputsToAdd . map ( item => item . nativeElement ) ) ;
327
+ const states = Array ( inputsToAdd . length ) . fill ( InputState . ready ) ;
328
+ this . inputsStates . splice ( this . inputsStates . length , 0 , ...states ) ;
329
+ }
330
+ else if ( list . length < this . inputs . length ) {
331
+ this . inputs . splice ( list . length ) ;
332
+ this . inputsStates . splice ( list . length ) ;
333
+ }
334
+
335
+ // filling the inputs after changing of their count
336
+ this . onInputCodeChanges ( ) ;
337
+ }
338
+
300
339
private focusOnInputAfterAppearing ( ) : void {
301
340
if ( ! this . state . isInitialFocusFieldEnabled ) {
302
341
return ;
0 commit comments