Skip to content

Commit 1c910c2

Browse files
committed
Release v 1.3.1:
- Fixing #21 #20 - Adjusted tslint issues
1 parent d05f28f commit 1c910c2

File tree

4 files changed

+55
-32
lines changed

4 files changed

+55
-32
lines changed

angular-code-input/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
# 1.3.1 (01.12.2020)
2+
**Note:** The following changes have been made:
3+
- The issue with inline component configuration has been resolved
4+
- Have fixed issues with readonly properties in Angular 11
5+
- Adjusting tslint issues
6+
17
# 1.3.0 (30.11.2020)
28
**Note:** The following changes have been made:
39
- Added the root config of the component

angular-code-input/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "angular-code-input",
3-
"version": "1.3.0",
3+
"version": "1.3.1",
44
"description": "Code or pin code input for Angular 7 - 11+ / Ionic 4, 5 + projects",
55
"keywords": ["angular", "pincode", "angular-pincode", "otp", "code-input", "angular-otp", "ionic-otp", "ionic-code-input", "ionic-pincode"],
66
"author": "Alexander Dmitrenko",

angular-code-input/src/lib/code-input.component.html

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
<span *ngFor="let holder of placeholders; index as i"
2-
[class.empty]="isInputElementEmptyAt(i)"
32
[class.code-hidden]="isCodeHidden">
43
<input #input
54
(click)="onClick($event)"

angular-code-input/src/lib/code-input.component.ts

Lines changed: 48 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -32,26 +32,29 @@ enum InputState {
3232
})
3333
export 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

Comments
 (0)