Angular form validators for passwords, emails, universal constraints, and credit cards with reactive and template-driven form support
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Angular directive support for using ngx-validators in template-driven forms with two-way data binding and declarative validation configuration.
Angular module that declares and exports all validator directives for use in template-driven forms.
@NgModule({
declarations: [
// Password validation
PasswordValidatorDirective,
// Email validation
EmailValidatorDirective,
EmailSuggestValidatorDirective,
// Universal validation
IsInRangeValidatorDirective,
IsNumberValidatorDirective,
MaxValidatorDirective,
MinValidatorDirective,
WhiteSpaceValidatorDirective,
EmptyStringValidatorDirective,
TypeValidatorDirective,
MinDateValidatorDirective,
MaxDateValidatorDirective,
// Credit card validation
CreditCardValidatorDirective,
// Equal to validation
EqualToDirective
],
exports: [/* same as declarations */]
})
export class ValidatorsModule {}Usage:
import { ValidatorsModule } from "ngx-validators";
@NgModule({
imports: [
CommonModule,
FormsModule,
ValidatorsModule // Import to use validator directives
],
// ...
})
export class MyModule {}Comprehensive password validation with configurable character requirements.
@Directive({
selector: "[password][formControlName],[password][formControl],[password][ngModel]"
})
export class PasswordValidatorDirective implements Validator, OnInit, OnChanges {
@Input() repeatCharacter: number = 4;
@Input() alphabeticalCharacter: number = 1;
@Input() digitCharacter: number = 1;
@Input() lowercaseCharacter: number = 1;
@Input() uppercaseCharacter: number = 1;
}Usage Example:
<input
type="password"
name="password"
[(ngModel)]="user.password"
#password="ngModel"
[password]="true"
[repeatCharacter]="3"
[alphabeticalCharacter]="2"
[digitCharacter]="1"
[lowercaseCharacter]="1"
[uppercaseCharacter]="1">
<div *ngIf="password.errors?.repeatCharacterRegexRule">
Cannot repeat characters more than {{password.errors.repeatCharacterRegexRule.repeatCount}} times.
</div>
<div *ngIf="password.errors?.digitCharacterRule">
Must contain at least {{password.errors.digitCharacterRule.required}} digit(s).
</div>
<div *ngIf="password.errors?.lowercaseCharacterRule">
Must contain at least {{password.errors.lowercaseCharacterRule.required}} lowercase letter(s).
</div>Basic email validation directive with configurable validation type.
@Directive({
selector: "[email][formControlName],[email][formControl],[email][ngModel]"
})
export class EmailValidatorDirective implements Validator, OnInit, OnChanges {
@Input() email: "normal" | "simple" = "normal";
}Usage Example:
<input
type="email"
name="email"
[(ngModel)]="user.email"
#email="ngModel"
[email]="'normal'">
<div *ngIf="email.errors?.normalEmailRule">
Please enter a valid email address.
</div>
<!-- Simple email validation -->
<input
type="email"
name="simpleEmail"
[(ngModel)]="user.simpleEmail"
#simpleEmail="ngModel"
[email]="'simple'">
<div *ngIf="simpleEmail.errors?.simpleEmailRule">
Please enter a valid email address.
</div>Email validation with intelligent typo suggestions and configurable options.
@Directive({
selector: "[emailSuggest][formControlName],[emailSuggest][formControl],[emailSuggest][ngModel]"
})
export class EmailSuggestValidatorDirective implements Validator, OnInit, OnChanges {
@Input() emailSuggest?: EmailOptions;
}Usage Example:
<input
type="email"
name="email"
[(ngModel)]="user.email"
#email="ngModel"
[emailSuggest]="customEmailOptions">
<div *ngIf="email.errors?.suggestion">
Did you mean: <strong>{{email.errors.suggestion.full}}</strong>?
</div>
<!-- With default options -->
<input
type="email"
name="defaultEmail"
[(ngModel)]="user.defaultEmail"
#defaultEmail="ngModel"
emailSuggest>Validates that input contains no whitespace characters.
@Directive({
selector: "[noWhitespace][formControlName],[noWhitespace][formControl],[noWhitespace][ngModel]"
})
export class WhiteSpaceValidatorDirective implements Validator {}Usage Example:
<input
name="username"
[(ngModel)]="user.username"
#username="ngModel"
noWhitespace>
<div *ngIf="username.errors?.noWhitespaceRequired">
Username cannot contain spaces.
</div>Validates that input is not empty after trimming whitespace.
@Directive({
selector: "[noEmptyString][formControlName],[noEmptyString][formControl],[noEmptyString][ngModel]"
})
export class EmptyStringValidatorDirective implements Validator {}Usage Example:
<input
name="description"
[(ngModel)]="item.description"
#description="ngModel"
noEmptyString>
<div *ngIf="description.errors?.noEmptyString">
Description cannot be empty.
</div>Validates that input is a valid number.
@Directive({
selector: "[isNumber][formControlName],[isNumber][formControl],[isNumber][ngModel]"
})
export class IsNumberValidatorDirective implements Validator {}Usage Example:
<input
name="age"
[(ngModel)]="user.age"
#age="ngModel"
isNumber>
<div *ngIf="age.errors?.numberRequired">
Please enter a valid number.
</div>Validates that numeric input is within a specified range.
@Directive({
selector: "[isInRange][formControlName],[isInRange][formControl],[isInRange][ngModel]"
})
export class IsInRangeValidatorDirective implements Validator, OnInit, OnChanges {
@Input() minValue: number = 0;
@Input() maxValue: number = 0;
}Usage Example:
<input
name="score"
[(ngModel)]="test.score"
#score="ngModel"
isInRange
[minValue]="0"
[maxValue]="100">
<div *ngIf="score.errors?.rangeValueToSmall">
Score must be at least {{score.errors.rangeValueToSmall.requiredMinValue}}.
</div>
<div *ngIf="score.errors?.rangeValueToBig">
Score cannot exceed {{score.errors.rangeValueToBig.requiredMaxValue}}.
</div>Validates minimum numeric value.
@Directive({
selector: "input[type=text][min][formControlName],input[type=text][min][formControl],input[type=text][min][ngModel]"
})
export class MinValidatorDirective implements Validator, OnInit, OnChanges {
@Input() min: number = 0;
}Usage Example:
<input
type="text"
name="price"
[(ngModel)]="product.price"
#price="ngModel"
[min]="0.01">
<div *ngIf="price.errors?.min">
Price must be at least ${{price.errors.min.required}}.
</div>Validates maximum numeric value.
@Directive({
selector: "input[type=text][max][formControlName],input[type=text][max][formControl],input[type=text][max][ngModel]"
})
export class MaxValidatorDirective implements Validator, OnInit, OnChanges {
@Input() max: number = 0;
}Usage Example:
<input
type="text"
name="discount"
[(ngModel)]="sale.discount"
#discount="ngModel"
[max]="100">
<div *ngIf="discount.errors?.max">
Discount cannot exceed {{discount.errors.max.required}}%.
</div>Validates minimum date value.
@Directive({
selector: "input[type=text][minDate][formControlName],input[type=text][minDate][formControl],input[type=text][minDate][ngModel]"
})
export class MinDateValidatorDirective implements Validator, OnInit, OnChanges {
@Input() minDate: string = "";
}Usage Example:
<input
type="text"
name="startDate"
[(ngModel)]="event.startDate"
#startDate="ngModel"
[minDate]="'2023-01-01'">
<div *ngIf="startDate.errors?.minDate">
Start date cannot be before {{startDate.errors.minDate.required | date}}.
</div>Validates maximum date value.
@Directive({
selector: "input[type=text][maxDate][formControlName],input[type=text][maxDate][formControl],input[type=text][maxDate][ngModel]"
})
export class MaxDateValidatorDirective implements Validator, OnInit, OnChanges {
@Input() maxDate: string = "";
}Usage Example:
<input
type="text"
name="endDate"
[(ngModel)]="event.endDate"
#endDate="ngModel"
[maxDate]="'2024-12-31'">
<div *ngIf="endDate.errors?.maxDate">
End date cannot be after {{endDate.errors.maxDate.required | date}}.
</div>Validates data type of input value.
@Directive({
selector: "input[requireType][formControlName]"
})
export class TypeValidatorDirective implements Validator, OnInit, OnChanges {
@Input() requiredType: "number" | "string" | "object" | "boolean" = "string";
}Usage Example:
<input
name="value"
formControlName="value"
[requiredType]="'string'"
requireType>
<div *ngIf="form.get('value')?.errors?.type">
Expected {{form.get('value')?.errors?.type.required}}
but got {{form.get('value')?.errors?.type.actual}}.
</div>Validates credit card format with configurable card type support.
@Directive({
selector: "[creditCard][formControlName],[creditCard][formControl],[creditCard][ngModel]"
})
export class CreditCardValidatorDirective implements Validator, OnInit, OnChanges {
@Input() creditCard: string = "all";
}Usage Example:
<!-- Accept any credit card -->
<input
type="text"
name="cardNumber"
[(ngModel)]="payment.cardNumber"
#cardNumber="ngModel"
[creditCard]="'all'">
<div *ngIf="cardNumber.errors?.creditcard">
Please enter a valid credit card number.
</div>
<!-- Accept only Visa cards -->
<input
type="text"
name="visaCard"
[(ngModel)]="payment.visaCard"
#visaCard="ngModel"
[creditCard]="'visa'">
<div *ngIf="visaCard.errors?.visa">
Please enter a valid Visa card number.
</div>
<!-- Other card types: 'americanExpress', 'dinersclub', 'discover', 'jcb', 'maestro', 'mastercard' -->Validates that two form controls have equal values.
@Directive({
selector: "[equalTo][ngModel], [equalTo][formControlName], [equalTo][formControl]"
})
export class EqualToDirective implements Validator, OnDestroy, OnChanges {
@Input() equalTo: string | AbstractControl;
}Usage Example:
<form>
<input
type="password"
name="password"
[(ngModel)]="user.password"
#password="ngModel">
<input
type="password"
name="confirmPassword"
[(ngModel)]="user.confirmPassword"
#confirmPassword="ngModel"
[equalTo]="'password'">
<div *ngIf="confirmPassword.errors?.notEqualTo">
Passwords do not match.
</div>
</form><form #userForm="ngForm">
<!-- Email with suggestion -->
<div>
<label>Email:</label>
<input
type="email"
name="email"
[(ngModel)]="user.email"
#email="ngModel"
emailSuggest
required>
<div *ngIf="email.errors?.suggestion">
Did you mean: <strong>{{email.errors.suggestion.full}}</strong>?
</div>
</div>
<!-- Password with complexity rules -->
<div>
<label>Password:</label>
<input
type="password"
name="password"
[(ngModel)]="user.password"
#password="ngModel"
[password]="true"
[digitCharacter]="1"
[lowercaseCharacter]="1"
[uppercaseCharacter]="1"
required>
<div *ngIf="password.errors?.digitCharacterRule">
Must contain at least 1 digit.
</div>
<div *ngIf="password.errors?.lowercaseCharacterRule">
Must contain at least 1 lowercase letter.
</div>
</div>
<!-- Password confirmation -->
<div>
<label>Confirm Password:</label>
<input
type="password"
name="confirmPassword"
[(ngModel)]="user.confirmPassword"
#confirmPassword="ngModel"
[equalTo]="'password'"
required>
<div *ngIf="confirmPassword.errors?.notEqualTo">
Passwords do not match.
</div>
</div>
<!-- Age with range validation -->
<div>
<label>Age:</label>
<input
type="text"
name="age"
[(ngModel)]="user.age"
#age="ngModel"
isNumber
[min]="18"
[max]="120"
required>
<div *ngIf="age.errors?.min">
Must be at least 18 years old.
</div>
<div *ngIf="age.errors?.max">
Age cannot exceed 120.
</div>
</div>
<!-- Credit card -->
<div>
<label>Credit Card:</label>
<input
type="text"
name="cardNumber"
[(ngModel)]="user.cardNumber"
#cardNumber="ngModel"
[creditCard]="'all'">
<div *ngIf="cardNumber.errors?.creditcard">
Please enter a valid credit card number.
</div>
</div>
<button type="submit" [disabled]="!userForm.valid">
Submit
</button>
</form>Directive Selectors: Each directive has specific attribute selectors that must be used exactly as shown.
Input Validation: Many directives require specific input types (e.g., type="text" for min/max date validators).
Error Objects: Error objects vary by validator type. Refer to individual validator documentation for specific error structures.
Form Module: Import FormsModule and ValidatorsModule in your Angular module to use template-driven forms with these validators.
TypeValidatorDirective: Currently only supports formControlName selector, limiting its use to reactive forms embedded in templates.