Skip to content

Commit

Permalink
feat(directives): allow directive inputs to be changed on runtime
Browse files Browse the repository at this point in the history
  • Loading branch information
Nightapes committed Apr 3, 2020
1 parent a44bc38 commit 6813a9e
Show file tree
Hide file tree
Showing 5 changed files with 195 additions and 16 deletions.
32 changes: 27 additions & 5 deletions src/components/creditcard/creditcard.directive.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
import { Directive, Input, forwardRef, OnInit } from "@angular/core";
import {
Directive,
Input,
forwardRef,
OnInit,
SimpleChanges
} from "@angular/core";
import {
NG_VALIDATORS,
Validator,
ValidatorFn,
AbstractControl
AbstractControl,
ValidationErrors
} from "@angular/forms";

import { CreditCardValidators } from "./creditcard-validators";
Expand All @@ -24,9 +31,14 @@ export class CreditCardValidatorDirective implements Validator, OnInit {
@Input() creditCard = "all";

private validator: ValidatorFn;
private onChange: () => void;

ngOnInit() {
switch (this.creditCard) {
this.setCreditcardValidator(this.creditCard);
}

setCreditcardValidator(type: string) {
switch (type) {
case "all":
this.validator = CreditCardValidators.isCreditCard;
break;
Expand Down Expand Up @@ -57,8 +69,18 @@ export class CreditCardValidatorDirective implements Validator, OnInit {
}
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
validate(c: AbstractControl): { [key: string]: any } {
ngOnChanges(changes: SimpleChanges): void {
if (changes["creditCard"]) {
this.setCreditcardValidator(changes["creditCard"].currentValue);
this.onChange();
}
}

validate(c: AbstractControl): ValidationErrors {
return this.validator(c);
}

registerOnValidatorChange(fn: () => void): void {
this.onChange = fn;
}
}
45 changes: 41 additions & 4 deletions src/components/email/email.directive.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import { EmailOptions } from "./email-util";
import { Directive, Input, forwardRef, OnInit } from "@angular/core";
import {
Directive,
Input,
forwardRef,
OnInit,
OnChanges,
SimpleChanges
} from "@angular/core";
import {
NG_VALIDATORS,
Validator,
Expand All @@ -21,13 +28,18 @@ import { EmailValidators } from "./email-validators";
}
]
})
export class EmailValidatorDirective implements Validator, OnInit {
@Input() email = "normal";
export class EmailValidatorDirective implements Validator, OnInit, OnChanges {
@Input() email: "normal" | "simple" = "normal";

private validator: ValidatorFn;
private onChange: () => void;

ngOnInit() {
switch (this.email) {
this.setValidator(this.email);
}

setValidator(type: string) {
switch (type) {
case "simple":
this.validator = EmailValidators.simple;
break;
Expand All @@ -40,6 +52,17 @@ export class EmailValidatorDirective implements Validator, OnInit {
}
}

ngOnChanges(changes: SimpleChanges): void {
if (changes["email"]) {
this.setValidator(changes["email"].currentValue);
this.onChange();
}
}

registerOnValidatorChange?(fn: () => void): void {
this.onChange = fn;
}

validate(c: AbstractControl): ValidationErrors {
return this.validator(c);
}
Expand All @@ -61,11 +84,25 @@ export class EmailSuggestValidatorDirective implements Validator, OnInit {
@Input() emailSuggest: EmailOptions;

private validator: ValidatorFn;
private onChange: () => void;

ngOnInit() {
this.validator = EmailValidators.suggest(this.emailSuggest);
}

ngOnChanges(changes: SimpleChanges): void {
if (changes["emailSuggest"]) {
this.validator = EmailValidators.suggest(
changes["emailSuggest"].currentValue
);
this.onChange();
}
}

registerOnValidatorChange?(fn: () => void): void {
this.onChange = fn;
}

validate(c: AbstractControl): ValidationErrors {
return this.validator(c);
}
Expand Down
23 changes: 21 additions & 2 deletions src/components/equal-to/equal-to.directive.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import { Directive, forwardRef, Input, OnDestroy } from "@angular/core";
import {
Directive,
forwardRef,
Input,
OnDestroy,
SimpleChanges,
OnChanges
} from "@angular/core";
import {
AbstractControl,
NG_VALIDATORS,
Expand All @@ -20,16 +27,18 @@ import { delay } from "rxjs/operators";
}
]
})
export class EqualToDirective implements Validator, OnDestroy {
export class EqualToDirective implements Validator, OnDestroy, OnChanges {
@Input() equalTo: string | AbstractControl;

private subscription: Subscription;
private onChange: () => void;

validate(c: AbstractControl): ValidationErrors | null {
const otherControl =
typeof this.equalTo === "string"
? c.parent.get(this.equalTo)
: this.equalTo;

if (!this.subscription) {
this.subscription = otherControl.valueChanges
.pipe(delay(1))
Expand All @@ -43,4 +52,14 @@ export class EqualToDirective implements Validator, OnDestroy {
ngOnDestroy(): void {
this.subscription.unsubscribe();
}

ngOnChanges(changes: SimpleChanges): void {
if (changes["equalTo"]) {
this.onChange();
}
}

registerOnValidatorChange(fn: () => void): void {
this.onChange = fn;
}
}
59 changes: 57 additions & 2 deletions src/components/password/password.directive.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import { Directive, Input, forwardRef, OnInit } from "@angular/core";
import {
Directive,
Input,
forwardRef,
OnInit,
SimpleChanges,
OnChanges
} from "@angular/core";
import {
NG_VALIDATORS,
Validator,
Expand All @@ -22,7 +29,8 @@ import { PasswordValidators } from "./password-validators";
}
]
})
export class PasswordValidatorDirective implements Validator, OnInit {
export class PasswordValidatorDirective
implements Validator, OnInit, OnChanges {
@Input() repeatCharacter = 4;
@Input() alphabeticalCharacter = 1;
@Input() digitCharacter = 1;
Expand All @@ -34,6 +42,7 @@ export class PasswordValidatorDirective implements Validator, OnInit {
private digitCharacterValidator: ValidatorFn;
private lowercaseCharacterValidator: ValidatorFn;
private uppercaseCharacterValidator: ValidatorFn;
private onChange: () => void;

ngOnInit() {
this.repeatCharacterValidator = PasswordValidators.repeatCharacterRegexRule(
Expand All @@ -53,6 +62,48 @@ export class PasswordValidatorDirective implements Validator, OnInit {
);
}

ngOnChanges(changes: SimpleChanges): void {
let inputChanged = false;
if (changes["repeatCharacter"]) {
this.repeatCharacterValidator = PasswordValidators.repeatCharacterRegexRule(
changes["repeatCharacter"].currentValue
);
inputChanged = true;
}

if (changes["alphabeticalCharacter"]) {
this.alphabeticalCharacterValidator = PasswordValidators.alphabeticalCharacterRule(
changes["alphabeticalCharacter"].currentValue
);
inputChanged = true;
}

if (changes["digitCharacter"]) {
this.digitCharacterValidator = PasswordValidators.digitCharacterRule(
changes["digitCharacter"].currentValue
);
inputChanged = true;
}

if (changes["lowercaseCharacter"]) {
this.lowercaseCharacterValidator = PasswordValidators.lowercaseCharacterRule(
changes["lowercaseCharacter"].currentValue
);
inputChanged = true;
}

if (changes["uppercaseCharacter"]) {
this.uppercaseCharacterValidator = PasswordValidators.uppercaseCharacterRule(
changes["uppercaseCharacter"].currentValue
);
inputChanged = true;
}

if (inputChanged) {
this.onChange();
}
}

validate(c: AbstractControl): ValidationErrors {
const compose: ValidatorFn = Validators.compose([
this.repeatCharacterValidator,
Expand All @@ -63,4 +114,8 @@ export class PasswordValidatorDirective implements Validator, OnInit {
]);
return compose(c);
}

registerOnValidatorChange(fn: () => void): void {
this.onChange = fn;
}
}
52 changes: 49 additions & 3 deletions src/components/universal/universal.directive.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import { Directive, forwardRef, Input, OnInit } from "@angular/core";
import {
Directive,
forwardRef,
Input,
OnInit,
OnChanges,
SimpleChanges
} from "@angular/core";
import {
AbstractControl,
NG_VALIDATORS,
Expand Down Expand Up @@ -98,6 +105,7 @@ export class IsInRangeValidatorDirective implements Validator, OnInit {
@Input() maxValue: number;

private validator: ValidatorFn;
private onChange: () => void;

ngOnInit() {
this.validator = UniversalValidators.isInRange(
Expand All @@ -106,9 +114,23 @@ export class IsInRangeValidatorDirective implements Validator, OnInit {
);
}

ngOnChanges(changes: SimpleChanges): void {
if (changes["minValue"] || changes["maxValue"]) {
this.validator = UniversalValidators.isInRange(
changes["minValue"].currentValue,
changes["maxValue"].currentValue
);
this.onChange();
}
}

validate(c: AbstractControl): ValidationErrors {
return this.validator(c);
}

registerOnValidatorChange(fn: () => void): void {
this.onChange = fn;
}
}

@Directive({
Expand All @@ -123,18 +145,30 @@ export class IsInRangeValidatorDirective implements Validator, OnInit {
}
]
})
export class MaxValidatorDirective implements Validator, OnInit {
export class MaxValidatorDirective implements Validator, OnInit, OnChanges {
@Input() max: number;

private validator: ValidatorFn;
private onChange: () => void;

ngOnInit() {
this.validator = UniversalValidators.max(this.max);
}

ngOnChanges(changes: SimpleChanges): void {
if (changes["max"]) {
this.validator = UniversalValidators.max(changes["max"].currentValue);
this.onChange();
}
}

validate(c: AbstractControl): ValidationErrors {
return this.validator(c);
}

registerOnValidatorChange(fn: () => void): void {
this.onChange = fn;
}
}

@Directive({
Expand All @@ -149,16 +183,28 @@ export class MaxValidatorDirective implements Validator, OnInit {
}
]
})
export class MinValidatorDirective implements Validator, OnInit {
export class MinValidatorDirective implements Validator, OnInit, OnChanges {
@Input() min: number;

private validator: ValidatorFn;
private onChange: () => void;

ngOnInit() {
this.validator = UniversalValidators.min(this.min);
}

ngOnChanges(changes: SimpleChanges): void {
if (changes["min"]) {
this.validator = UniversalValidators.min(changes["min"].currentValue);
this.onChange();
}
}

validate(c: AbstractControl): ValidationErrors {
return this.validator(c);
}

registerOnValidatorChange(fn: () => void): void {
this.onChange = fn;
}
}

0 comments on commit 6813a9e

Please # to comment.