Angular cross field validation with template forms

<form>
<label>Start date:
<input type="date" name="startDate" [(ngModel)]="startDate" required>
</label>
<br>
<label>End date:
<input #endDateInput="ngModel" type="date" name="endDate" [(ngModel)]="endDate" required>
</label>
</form>
import { Directive, Input } from "@angular/core";
import { Validator, AbstractControl, NG_VALIDATORS } from "@angular/forms";
@Directive({
selector: "[afterDate]",
providers: [
{ provide: NG_VALIDATORS, useExisting: AfterDateDirective, multi: true }
]
})
export class AfterDateDirective implements Validator {
@Input()
afterDate: Date;
validate(c: AbstractControl): { [key: string]: any } {
if (c.value && this.afterDate && c.value < this.afterDate) {
return {
afterDate: true
};
}
return null;
}
}
<form>
<label>Start date:
<input type="date" name="startDate" [(ngModel)]="startDate" required>
</label>
<br>
<label>End date:
<input #endDateInput="ngModel" type="date" name="endDate" [(ngModel)]="endDate" required [afterDate]="startDate">
</label>
<span class="error" *ngIf="endDateInput.errors?.afterDate">Must be after start date</span>
</form>
import { Directive, Input, OnChanges, SimpleChanges } from "@angular/core";
import { Validator, AbstractControl, NG_VALIDATORS } from "@angular/forms";
@Directive({
selector: "[afterDate]",
providers: [
{ provide: NG_VALIDATORS, useExisting: AfterDateDirective, multi: true }
]
})
export class AfterDateDirective implements Validator, OnChanges {
@Input()
afterDate: Date;
validate(c: AbstractControl): { [key: string]: any } {
if (c.value && this.afterDate && c.value < this.afterDate) {
return {
afterDate: true
};
}
return null;
}
onChange: () => void; registerOnValidatorChange(fn: () => void): void {
this.onChange = fn;
}
ngOnChanges(changes: SimpleChanges): void {
if ('afterDate' in changes && this.onChange) {
this.onChange();
}
}
}
import { SimpleChanges, OnChanges, Directive, Inject } from '@angular/core';@Directive({ selector: 'validatorBase' })
export class ValidatorBaseDirective implements OnChanges {
private inputs: string[];
onChange: () => void; constructor(@Inject([]) ...inputs: string[]) {
this.inputs = inputs;
}
registerOnValidatorChange(fn: () => void): void {
this.onChange = fn;
}
ngOnChanges(changes: SimpleChanges): void {
if (this.inputs.some((input) => input in changes) && this.onChange) {
this.onChange();
}
}
}
import { Directive, Input, SimpleChanges } from "@angular/core";
import { Validator, AbstractControl, NG_VALIDATORS } from "@angular/forms";
import { ValidatorBaseDirective } from './validator-base.directive';@Directive({
selector: "[afterDate]",
providers: [
{ provide: NG_VALIDATORS, useExisting: AfterDateDirective, multi: true }
]
})
export class AfterDateDirective extends ValidatorBaseDirective implements Validator {
@Input()
afterDate: Date;
constructor() {
super('afterDate');
}
validate(c: AbstractControl): { [key: string]: any } {
if (c.value && this.afterDate && c.value < this.afterDate) {
return {
afterDate: true
};
}
return null;
}
}

--

--

--

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

NestJS — How to use TypeOrm?

Getting in Touch via EmailJS

Create a Tic Tac Toe Game using NEXT JS

Code JS in Stlye: Early Return

Tutorial | Creating a form with React + Redux

Patch, Put & Delete APIs

React basics and component deep dive

Is It Time for the JavaScript Temporal API?

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Adrian Brand

Adrian Brand

More from Medium

How to fix “ng: command not found” in angular

How to fix

The MVC Architecture in Angular

Introduction to Angular Forms

How to start learning Angular? Discover the basic concepts

How to start learning Angular?