Angular 2 form validations start date <= end date
Based on the answer of santiagomaldonado I have created a generic ValidatorFn that can be used in multiple Reactive Forms with a dynamic return value.
export class DateValidators {
static dateLessThan(dateField1: string, dateField2: string, validatorField: { [key: string]: boolean }): ValidatorFn {
return (c: AbstractControl): { [key: string]: boolean } | null => {
const date1 = c.get(dateField1).value;
const date2 = c.get(dateField2).value;
if ((date1 !== null && date2 !== null) && date1 > date2) {
return validatorField;
}
return null;
};
}
}
Import the validator and use it like this in your formgroup validators.
this.form = this.fb.group({
loadDate: null,
deliveryDate: null,
}, { validator: Validators.compose([
DateValidators.dateLessThan('loadDate', 'deliveryDate', { 'loaddate': true }),
DateValidators.dateLessThan('cargoLoadDate', 'cargoDeliveryDate', { 'cargoloaddate': true })
])});
Now you can use the validation in HTML.
<md-error *ngIf="form.hasError('loaddate')">Load date must be before delivery date</md-error>
You can also do it with Reactive Forms. The FormBuilder API lets you add custom validators.
Valid keys for the extra parameter map are validator and asyncValidator
Example:
import { Component } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
@Component({
selector: 'reactive-form',
templateUrl: './reactive-form.html'
})
export class ReactiveFormComponent {
form: FormGroup
constructor(private fb: FormBuilder){
this.createForm();
}
createForm() {
this.form = this.fb.group({
dateTo: ['', Validators.required ],
dateFrom: ['', Validators.required ]
}, {validator: this.dateLessThan('dateFrom', 'dateTo')});
}
dateLessThan(from: string, to: string) {
return (group: FormGroup): {[key: string]: any} => {
let f = group.controls[from];
let t = group.controls[to];
if (f.value > t.value) {
return {
dates: "Date from should be less than Date to"
};
}
return {};
}
}
}
Note that I'm comparing the values of the inputs date and from with >, but by default this would be comparing strings. In the live example I'm using angular-date-value-accessor and importing the directive useValueAsDate.
<input formControlName="dateFrom" type="date" useValueAsDate />
With this directive group.controls[from].value and group.controls[to].value returns Date and then I can compare them with <.
Live example in plunkr
Credits to Dave's answer