@@ -32,26 +32,29 @@ enum InputState {
3232} )
3333export class CodeInputComponent implements AfterViewInit , OnInit , OnChanges , AfterViewChecked , CodeInputComponentConfig {
3434
35- @ViewChildren ( 'input' ) inputsList : QueryList < ElementRef > ;
35+ @ViewChildren ( 'input' ) inputsList ! : QueryList < ElementRef > ;
3636
37- @Input ( ) readonly codeLength ;
38- @Input ( ) readonly inputType ;
39- @Input ( ) readonly initialFocusField ?: number ;
37+ @Input ( ) codeLength ! : number ;
38+ @Input ( ) inputType ! : string ;
39+ @Input ( ) initialFocusField ?: number ;
4040 /** @deprecated Use isCharsCode prop instead. */
4141 @Input ( ) isNonDigitsCode = false ;
42- @Input ( ) isCharsCode ;
43- @Input ( ) isCodeHidden ;
44- @Input ( ) isPrevFocusableAfterClearing ;
45- @Input ( ) isFocusingOnLastByClickIfFilled ;
46- @Input ( ) code ?: string | number ;
42+ @Input ( ) isCharsCode ! : boolean ;
43+ @Input ( ) isCodeHidden ! : boolean ;
44+ @Input ( ) isPrevFocusableAfterClearing ! : boolean ;
45+ @Input ( ) isFocusingOnLastByClickIfFilled ! : boolean ;
46+ @Input ( ) code ?: string | number ;
4747
4848 @Output ( ) readonly codeChanged = new EventEmitter < string > ( ) ;
4949 @Output ( ) readonly codeCompleted = new EventEmitter < string > ( ) ;
5050
51- public placeholders : number [ ] ;
51+ public placeholders ! : number [ ] ;
5252
5353 private inputs : HTMLInputElement [ ] = [ ] ;
5454 private inputsStates : InputState [ ] = [ ] ;
55+
56+ // tslint:disable-next-line:variable-name
57+ private _codeLength ! : number ;
5558 private state = {
5659 isFocusingAfterAppearingCompleted : false ,
5760 isInitialFocusFieldEnabled : false
@@ -74,6 +77,7 @@ export class CodeInputComponent implements AfterViewInit, OnInit, OnChanges, Aft
7477 continue ;
7578 }
7679
80+ // @ts -ignore
7781 this [ prop ] = config [ prop ] ;
7882 }
7983 }
@@ -83,7 +87,9 @@ export class CodeInputComponent implements AfterViewInit, OnInit, OnChanges, Aft
8387 */
8488
8589 ngOnInit ( ) : void {
86- this . placeholders = Array ( this . codeLength ) . fill ( 1 ) ;
90+ // defining internal code length prop for skipping external prop updates
91+ this . _codeLength = this . codeLength ;
92+ this . placeholders = Array ( this . _codeLength ) . fill ( 1 ) ;
8793 this . state . isInitialFocusFieldEnabled = ! this . isEmpty ( this . initialFocusField ) ;
8894 }
8995
@@ -118,14 +124,14 @@ export class CodeInputComponent implements AfterViewInit, OnInit, OnChanges, Aft
118124 }
119125
120126 const target = e . target ;
121- const last = this . inputs [ this . codeLength - 1 ] ;
127+ const last = this . inputs [ this . _codeLength - 1 ] ;
122128 // already focused
123129 if ( target === last ) {
124130 return ;
125131 }
126132
127133 // check filling
128- const isFilled = this . getCurrentFilledCode ( ) . length >= this . codeLength ;
134+ const isFilled = this . getCurrentFilledCode ( ) . length >= this . _codeLength ;
129135 if ( ! isFilled ) {
130136 return ;
131137 }
@@ -155,7 +161,7 @@ export class CodeInputComponent implements AfterViewInit, OnInit, OnChanges, Aft
155161 this . setInputValue ( target , value . toString ( ) . charAt ( 0 ) ) ;
156162 this . emitChanges ( ) ;
157163
158- if ( next > this . codeLength - 1 ) {
164+ if ( next > this . _codeLength - 1 ) {
159165 target . blur ( ) ;
160166 return ;
161167 }
@@ -174,7 +180,8 @@ export class CodeInputComponent implements AfterViewInit, OnInit, OnChanges, Aft
174180 }
175181
176182 // Convert paste text into iterable
177- const values = data . split ( '' ) ;
183+ // tslint:disable-next-line:no-non-null-assertion
184+ const values = data ! . split ( '' ) ;
178185 let valIndex = 0 ;
179186
180187 for ( let j = i ; j < this . inputs . length ; j ++ ) {
@@ -228,15 +235,6 @@ export class CodeInputComponent implements AfterViewInit, OnInit, OnChanges, Aft
228235 }
229236 }
230237
231- isInputElementEmptyAt ( index : number ) : boolean {
232- const input = this . inputs [ index ] ;
233- if ( ! input ) {
234- return true ;
235- }
236-
237- return this . isEmpty ( input . value ) ;
238- }
239-
240238 private onInputCodeChanges ( ) : void {
241239 if ( ! this . inputs . length ) {
242240 return ;
@@ -249,16 +247,20 @@ export class CodeInputComponent implements AfterViewInit, OnInit, OnChanges, Aft
249247 return ;
250248 }
251249
252- const chars = this . code . toString ( ) . trim ( ) . split ( '' ) ;
250+ // tslint:disable-next-line:no-non-null-assertion
251+ const chars = this . code ! . toString ( ) . trim ( ) . split ( '' ) ;
253252 // checking if all the values are correct
253+ let isAllCharsAreAllowed = true ;
254254 for ( const char of chars ) {
255255 if ( ! this . canInputValue ( char ) ) {
256- return ;
256+ isAllCharsAreAllowed = false ;
257+ break ;
257258 }
258259 }
259260
260261 this . inputs . forEach ( ( input : HTMLInputElement , index : number ) => {
261- this . setInputValue ( input , chars [ index ] ) ;
262+ const value = isAllCharsAreAllowed ? chars [ index ] : null ;
263+ this . setInputValue ( input , value ) ;
262264 } ) ;
263265 }
264266
@@ -271,6 +273,10 @@ export class CodeInputComponent implements AfterViewInit, OnInit, OnChanges, Aft
271273 return ;
272274 }
273275
276+ if ( ! this . initialFocusField ) {
277+ return ;
278+ }
279+
274280 this . inputs [ this . initialFocusField ] . focus ( ) ;
275281 this . state . isFocusingAfterAppearingCompleted = document . activeElement === this . inputs [ this . initialFocusField ] ;
276282 }
@@ -284,7 +290,7 @@ export class CodeInputComponent implements AfterViewInit, OnInit, OnChanges, Aft
284290
285291 this . codeChanged . emit ( code ) ;
286292
287- if ( code . length >= this . codeLength ) {
293+ if ( code . length >= this . _codeLength ) {
288294 this . codeCompleted . emit ( code ) ;
289295 }
290296 }
@@ -327,8 +333,20 @@ export class CodeInputComponent implements AfterViewInit, OnInit, OnChanges, Aft
327333
328334 private setInputValue ( input : HTMLInputElement , value : any ) : void {
329335 const isEmpty = this . isEmpty ( value ) ;
330- input . value = isEmpty ? null : value ;
331- input . className = isEmpty ? '' : 'has-value' ;
336+ const valueClassCSS = 'has-value' ;
337+ const emptyClassCSS = 'empty' ;
338+ if ( isEmpty ) {
339+ input . value = '' ;
340+ input . classList . remove ( valueClassCSS ) ;
341+ // tslint:disable-next-line:no-non-null-assertion
342+ input . parentElement ! . classList . add ( emptyClassCSS ) ;
343+ }
344+ else {
345+ input . value = value ;
346+ input . classList . add ( valueClassCSS ) ;
347+ // tslint:disable-next-line:no-non-null-assertion
348+ input . parentElement ! . classList . remove ( emptyClassCSS ) ;
349+ }
332350 }
333351
334352 private canInputValue ( value : any ) : boolean {
0 commit comments