77 Inject ,
88 Input ,
99 OnChanges ,
10+ OnDestroy ,
1011 OnInit ,
1112 Optional ,
1213 Output ,
@@ -19,6 +20,7 @@ import {
1920 CodeInputComponentConfigToken ,
2021 defaultComponentConfig
2122} from './code-input.component.config' ;
23+ import { Subscription } from 'rxjs' ;
2224
2325enum InputState {
2426 ready = 0 ,
@@ -31,7 +33,7 @@ enum InputState {
3133 templateUrl : 'code-input.component.html' ,
3234 styleUrls : [ './code-input.component.scss' ]
3335} )
34- export class CodeInputComponent implements AfterViewInit , OnInit , OnChanges , AfterViewChecked , CodeInputComponentConfig {
36+ export class CodeInputComponent implements AfterViewInit , OnInit , OnChanges , OnDestroy , AfterViewChecked , CodeInputComponentConfig {
3537
3638 @ViewChildren ( 'input' ) inputsList ! : QueryList < ElementRef > ;
3739
@@ -51,10 +53,11 @@ export class CodeInputComponent implements AfterViewInit, OnInit, OnChanges, Aft
5153 @Output ( ) readonly codeChanged = new EventEmitter < string > ( ) ;
5254 @Output ( ) readonly codeCompleted = new EventEmitter < string > ( ) ;
5355
54- public placeholders ! : number [ ] ;
56+ public placeholders : number [ ] = [ ] ;
5557
5658 private inputs : HTMLInputElement [ ] = [ ] ;
5759 private inputsStates : InputState [ ] = [ ] ;
60+ private inputsListSubscription ! : Subscription ;
5861
5962 // tslint:disable-next-line:variable-name
6063 private _codeLength ! : number ;
@@ -90,20 +93,16 @@ export class CodeInputComponent implements AfterViewInit, OnInit, OnChanges, Aft
9093 */
9194
9295 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
9697 this . state . isInitialFocusFieldEnabled = ! this . isEmpty ( this . initialFocusField ) ;
98+ // initiating the code
99+ this . onCodeLengthChanges ( ) ;
97100 }
98101
99102 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 ) ;
107106 }
108107
109108 ngAfterViewChecked ( ) : void {
@@ -114,6 +113,15 @@ export class CodeInputComponent implements AfterViewInit, OnInit, OnChanges, Aft
114113 if ( changes . code ) {
115114 this . onInputCodeChanges ( ) ;
116115 }
116+ if ( changes . codeLength ) {
117+ this . onCodeLengthChanges ( ) ;
118+ }
119+ }
120+
121+ ngOnDestroy ( ) : void {
122+ if ( this . inputsListSubscription ) {
123+ this . inputsListSubscription . unsubscribe ( ) ;
124+ }
117125 }
118126
119127 /**
@@ -297,6 +305,37 @@ export class CodeInputComponent implements AfterViewInit, OnInit, OnChanges, Aft
297305 } ) ;
298306 }
299307
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+
300339 private focusOnInputAfterAppearing ( ) : void {
301340 if ( ! this . state . isInitialFocusFieldEnabled ) {
302341 return ;
0 commit comments