Skip to content

Commit 221fda2

Browse files
committed
fix(directives): don't trigger validation changed on the first ngOnChanges call
1 parent e0595ff commit 221fda2

File tree

7 files changed

+111
-220
lines changed

7 files changed

+111
-220
lines changed

examples/package-lock.json

Lines changed: 0 additions & 21 deletions
This file was deleted.

examples/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
"core-js": "^2.4.1",
2929
"hammerjs": "^2.0.8",
3030
"ngx-highlightjs": "^2.1.1",
31-
"ngx-validators": "5.2.0",
31+
"ngx-validators": "file:../dist",
3232
"rxjs": "^6.2.2",
3333
"zone.js": "^0.8.5"
3434
},

src/components/creditcard/creditcard.directive.ts

Lines changed: 9 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,20 @@
1-
import {
2-
Directive,
3-
Input,
4-
forwardRef,
5-
OnInit,
6-
SimpleChanges
7-
} from "@angular/core";
8-
import {
9-
NG_VALIDATORS,
10-
Validator,
11-
ValidatorFn,
12-
AbstractControl,
13-
ValidationErrors
14-
} from "@angular/forms";
1+
import { Directive, Input, forwardRef, OnInit, SimpleChanges, OnChanges } from "@angular/core";
2+
import { NG_VALIDATORS, Validator, ValidatorFn, AbstractControl, ValidationErrors } from "@angular/forms";
153

164
import { CreditCardValidators } from "./creditcard-validators";
175

186
@Directive({
19-
selector:
20-
"[creditCard][formControlName],[creditCard][formControl],[creditCard][ngModel]",
7+
selector: "[creditCard][formControlName],[creditCard][formControl],[creditCard][ngModel]",
218
providers: [
229
{
2310
provide: NG_VALIDATORS,
2411
// eslint-disable-next-line @typescript-eslint/no-use-before-define
2512
useExisting: forwardRef(() => CreditCardValidatorDirective),
26-
multi: true
27-
}
28-
]
13+
multi: true,
14+
},
15+
],
2916
})
30-
export class CreditCardValidatorDirective implements Validator, OnInit {
17+
export class CreditCardValidatorDirective implements Validator, OnInit, OnChanges {
3118
@Input() creditCard = "all";
3219

3320
private validator: ValidatorFn;
@@ -70,8 +57,8 @@ export class CreditCardValidatorDirective implements Validator, OnInit {
7057
}
7158

7259
ngOnChanges(changes: SimpleChanges): void {
73-
if (changes["creditCard"]) {
74-
this.setCreditcardValidator(changes["creditCard"].currentValue);
60+
if (changes.creditCard && !changes.creditCard.isFirstChange()) {
61+
this.setCreditcardValidator(changes.creditCard.currentValue);
7562
this.onChange();
7663
}
7764
}

src/components/email/email.directive.ts

Lines changed: 14 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,6 @@
11
import { EmailOptions } from "./email-util";
2-
import {
3-
Directive,
4-
Input,
5-
forwardRef,
6-
OnInit,
7-
OnChanges,
8-
SimpleChanges
9-
} from "@angular/core";
10-
import {
11-
NG_VALIDATORS,
12-
Validator,
13-
ValidatorFn,
14-
AbstractControl,
15-
ValidationErrors
16-
} from "@angular/forms";
2+
import { Directive, Input, forwardRef, OnInit, OnChanges, SimpleChanges } from "@angular/core";
3+
import { NG_VALIDATORS, Validator, ValidatorFn, AbstractControl, ValidationErrors } from "@angular/forms";
174

185
import { EmailValidators } from "./email-validators";
196

@@ -24,9 +11,9 @@ import { EmailValidators } from "./email-validators";
2411
provide: NG_VALIDATORS,
2512
// tslint:disable-next-line:no-forward-ref
2613
useExisting: forwardRef(() => EmailValidatorDirective),
27-
multi: true
28-
}
29-
]
14+
multi: true,
15+
},
16+
],
3017
})
3118
export class EmailValidatorDirective implements Validator, OnInit, OnChanges {
3219
@Input() email: "normal" | "simple" = "normal";
@@ -53,8 +40,8 @@ export class EmailValidatorDirective implements Validator, OnInit, OnChanges {
5340
}
5441

5542
ngOnChanges(changes: SimpleChanges): void {
56-
if (changes["email"]) {
57-
this.setValidator(changes["email"].currentValue);
43+
if (changes.email && !changes.email.isFirstChange()) {
44+
this.setValidator(changes.email.currentValue);
5845
this.onChange();
5946
}
6047
}
@@ -69,18 +56,17 @@ export class EmailValidatorDirective implements Validator, OnInit, OnChanges {
6956
}
7057

7158
@Directive({
72-
selector:
73-
"[emailSuggest][formControlName],[emailSuggest][formControl],[emailSuggest][ngModel]",
59+
selector: "[emailSuggest][formControlName],[emailSuggest][formControl],[emailSuggest][ngModel]",
7460
providers: [
7561
{
7662
provide: NG_VALIDATORS,
7763
// tslint:disable-next-line:no-forward-ref
7864
useExisting: forwardRef(() => EmailSuggestValidatorDirective),
79-
multi: true
80-
}
81-
]
65+
multi: true,
66+
},
67+
],
8268
})
83-
export class EmailSuggestValidatorDirective implements Validator, OnInit {
69+
export class EmailSuggestValidatorDirective implements Validator, OnInit, OnChanges {
8470
@Input() emailSuggest: EmailOptions;
8571

8672
private validator: ValidatorFn;
@@ -91,10 +77,8 @@ export class EmailSuggestValidatorDirective implements Validator, OnInit {
9177
}
9278

9379
ngOnChanges(changes: SimpleChanges): void {
94-
if (changes["emailSuggest"]) {
95-
this.validator = EmailValidators.suggest(
96-
changes["emailSuggest"].currentValue
97-
);
80+
if (changes.emailSuggest && !changes.emailSuggest.isFirstChange()) {
81+
this.validator = EmailValidators.suggest(changes.emailSuggest.currentValue);
9882
this.onChange();
9983
}
10084
}

src/components/equal-to/equal-to.directive.ts

Lines changed: 11 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,18 @@
1-
import {
2-
Directive,
3-
forwardRef,
4-
Input,
5-
OnDestroy,
6-
SimpleChanges,
7-
OnChanges
8-
} from "@angular/core";
9-
import {
10-
AbstractControl,
11-
NG_VALIDATORS,
12-
ValidationErrors,
13-
Validator
14-
} from "@angular/forms";
1+
import { Directive, forwardRef, Input, OnDestroy, SimpleChanges, OnChanges } from "@angular/core";
2+
import { AbstractControl, NG_VALIDATORS, ValidationErrors, Validator } from "@angular/forms";
153
import { Subscription } from "rxjs";
164
import { delay } from "rxjs/operators";
175

186
@Directive({
19-
selector:
20-
"[equalTo][ngModel], [equalTo][formControlName], [equalTo][formControl]",
7+
selector: "[equalTo][ngModel], [equalTo][formControlName], [equalTo][formControl]",
218
providers: [
229
{
2310
provide: NG_VALIDATORS,
2411
// tslint:disable-next-line:no-forward-ref
2512
useExisting: forwardRef(() => EqualToDirective),
26-
multi: true
27-
}
28-
]
13+
multi: true,
14+
},
15+
],
2916
})
3017
export class EqualToDirective implements Validator, OnDestroy, OnChanges {
3118
@Input() equalTo: string | AbstractControl;
@@ -34,17 +21,12 @@ export class EqualToDirective implements Validator, OnDestroy, OnChanges {
3421
private onChange: () => void;
3522

3623
validate(c: AbstractControl): ValidationErrors | null {
37-
const otherControl =
38-
typeof this.equalTo === "string"
39-
? c.parent.get(this.equalTo)
40-
: this.equalTo;
24+
const otherControl = typeof this.equalTo === "string" ? c.parent.get(this.equalTo) : this.equalTo;
4125

4226
if (!this.subscription) {
43-
this.subscription = otherControl.valueChanges
44-
.pipe(delay(1))
45-
.subscribe(() => {
46-
c.updateValueAndValidity();
47-
});
27+
this.subscription = otherControl.valueChanges.pipe(delay(1)).subscribe(() => {
28+
c.updateValueAndValidity();
29+
});
4830
}
4931
return c.value !== otherControl.value ? { notEqualTo: true } : null;
5032
}
@@ -54,7 +36,7 @@ export class EqualToDirective implements Validator, OnDestroy, OnChanges {
5436
}
5537

5638
ngOnChanges(changes: SimpleChanges): void {
57-
if (changes["equalTo"]) {
39+
if (changes.equalTo && !changes.equalTo.isFirstChange()) {
5840
this.onChange();
5941
}
6042
}

src/components/password/password.directive.ts

Lines changed: 28 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,20 @@
1-
import {
2-
Directive,
3-
Input,
4-
forwardRef,
5-
OnInit,
6-
SimpleChanges,
7-
OnChanges
8-
} from "@angular/core";
9-
import {
10-
NG_VALIDATORS,
11-
Validator,
12-
Validators,
13-
ValidatorFn,
14-
AbstractControl,
15-
ValidationErrors
16-
} from "@angular/forms";
1+
import { Directive, Input, forwardRef, OnInit, SimpleChanges, OnChanges } from "@angular/core";
2+
import { NG_VALIDATORS, Validator, Validators, ValidatorFn, AbstractControl, ValidationErrors } from "@angular/forms";
173

184
import { PasswordValidators } from "./password-validators";
195

206
@Directive({
21-
selector:
22-
"[password][formControlName],[password][formControl],[password][ngModel]",
7+
selector: "[password][formControlName],[password][formControl],[password][ngModel]",
238
providers: [
249
{
2510
provide: NG_VALIDATORS,
2611
// tslint:disable-next-line:no-forward-ref
2712
useExisting: forwardRef(() => PasswordValidatorDirective),
28-
multi: true
29-
}
30-
]
13+
multi: true,
14+
},
15+
],
3116
})
32-
export class PasswordValidatorDirective
33-
implements Validator, OnInit, OnChanges {
17+
export class PasswordValidatorDirective implements Validator, OnInit, OnChanges {
3418
@Input() repeatCharacter = 4;
3519
@Input() alphabeticalCharacter = 1;
3620
@Input() digitCharacter = 1;
@@ -45,58 +29,44 @@ export class PasswordValidatorDirective
4529
private onChange: () => void;
4630

4731
ngOnInit() {
48-
this.repeatCharacterValidator = PasswordValidators.repeatCharacterRegexRule(
49-
this.repeatCharacter
50-
);
51-
this.alphabeticalCharacterValidator = PasswordValidators.alphabeticalCharacterRule(
52-
this.alphabeticalCharacter
53-
);
54-
this.digitCharacterValidator = PasswordValidators.digitCharacterRule(
55-
this.digitCharacter
56-
);
57-
this.lowercaseCharacterValidator = PasswordValidators.lowercaseCharacterRule(
58-
this.lowercaseCharacter
59-
);
60-
this.uppercaseCharacterValidator = PasswordValidators.uppercaseCharacterRule(
61-
this.uppercaseCharacter
62-
);
32+
this.repeatCharacterValidator = PasswordValidators.repeatCharacterRegexRule(this.repeatCharacter);
33+
this.alphabeticalCharacterValidator = PasswordValidators.alphabeticalCharacterRule(this.alphabeticalCharacter);
34+
this.digitCharacterValidator = PasswordValidators.digitCharacterRule(this.digitCharacter);
35+
this.lowercaseCharacterValidator = PasswordValidators.lowercaseCharacterRule(this.lowercaseCharacter);
36+
this.uppercaseCharacterValidator = PasswordValidators.uppercaseCharacterRule(this.uppercaseCharacter);
6337
}
6438

6539
ngOnChanges(changes: SimpleChanges): void {
6640
let inputChanged = false;
67-
if (changes["repeatCharacter"]) {
68-
this.repeatCharacterValidator = PasswordValidators.repeatCharacterRegexRule(
69-
changes["repeatCharacter"].currentValue
70-
);
71-
inputChanged = true;
41+
if (changes.repeatCharacter) {
42+
this.repeatCharacterValidator = PasswordValidators.repeatCharacterRegexRule(changes.repeatCharacter.currentValue);
43+
inputChanged = changes.repeatCharacter.isFirstChange() ? false : true;
7244
}
7345

74-
if (changes["alphabeticalCharacter"]) {
46+
if (changes.alphabeticalCharacter) {
7547
this.alphabeticalCharacterValidator = PasswordValidators.alphabeticalCharacterRule(
76-
changes["alphabeticalCharacter"].currentValue
48+
changes.alphabeticalCharacter.currentValue
7749
);
78-
inputChanged = true;
50+
inputChanged = changes.alphabeticalCharacter.isFirstChange() ? false : true;
7951
}
8052

81-
if (changes["digitCharacter"]) {
82-
this.digitCharacterValidator = PasswordValidators.digitCharacterRule(
83-
changes["digitCharacter"].currentValue
84-
);
85-
inputChanged = true;
53+
if (changes.digitCharacter) {
54+
this.digitCharacterValidator = PasswordValidators.digitCharacterRule(changes.digitCharacter.currentValue);
55+
inputChanged = changes.digitCharacter.isFirstChange() ? false : true;
8656
}
8757

88-
if (changes["lowercaseCharacter"]) {
58+
if (changes.lowercaseCharacter) {
8959
this.lowercaseCharacterValidator = PasswordValidators.lowercaseCharacterRule(
90-
changes["lowercaseCharacter"].currentValue
60+
changes.lowercaseCharacter.currentValue
9161
);
92-
inputChanged = true;
62+
inputChanged = changes.lowercaseCharacter.isFirstChange() ? false : true;
9363
}
9464

95-
if (changes["uppercaseCharacter"]) {
65+
if (changes.uppercaseCharacter) {
9666
this.uppercaseCharacterValidator = PasswordValidators.uppercaseCharacterRule(
97-
changes["uppercaseCharacter"].currentValue
67+
changes.uppercaseCharacter.currentValue
9868
);
99-
inputChanged = true;
69+
inputChanged = changes.uppercaseCharacter.isFirstChange() ? false : true;
10070
}
10171

10272
if (inputChanged) {
@@ -110,7 +80,7 @@ export class PasswordValidatorDirective
11080
this.digitCharacterValidator,
11181
this.alphabeticalCharacterValidator,
11282
this.lowercaseCharacterValidator,
113-
this.uppercaseCharacterValidator
83+
this.uppercaseCharacterValidator,
11484
]);
11585
return compose(c);
11686
}

0 commit comments

Comments
 (0)