I am building a component (html
, css
, spec.ts
, ts
) in angular in which I always want endDate > startDate
. I have followed this link https://material.angular.io/components/datepicker/overview in order make multiple datepickers.
This is the html
which I have used for startDate and endDate.
startDate:
<div class="item item-1" fxFlex="50%" fxFlexOrder="1">
<mat-form-field>
<input matInput [matDatepicker]="picker1" placeholder="{{'PORTAL.STARTDATE' | translate}}" type="text" formControlName="startDate" [(ngModel)]="unavailability.startDate" [readonly]="!componentPermission.writePermission">
<mat-datepicker-toggle matSuffix [for]="picker1"></mat-datepicker-toggle>
<mat-datepicker #picker1></mat-datepicker>
</mat-form-field>
</div>
endDate:
<div class="item item-2" fxFlex="50%" fxFlexOrder="2">
<mat-form-field>
<input matInput [matDatepicker]="picker2" placeholder="{{'PORTAL.ENDDATE' | translate}}" type="text" formControlName="endDate" [(ngModel)]="unavailability.endDate" [readonly]="!componentPermission.writePermission">
<mat-datepicker-toggle matSuffix [for]="picker2"></mat-datepicker-toggle>
<mat-datepicker #picker2></mat-datepicker>
</mat-form-field>
</div>
The validateForm()
code which I have used in the ts
is:
validateForm() {
this.unavailabilityForm = this.formBuilder.group({
'startDate': [''],
'endDate': ['']
});
}
I am pretty sure I have to make some changes in the validateForm()
code but I am not sure what changes I have to make.
Since you seem to be going with a mix of reactive form and template driven, I would choose a reactive form completely. Implementing Validation is also in my opinion easier and cleaner. This also then means, you can drop ngModel
altogether, which I would then strongly suggest, since it can cause unexpected issues to have two bindings (form control and ngModel). EDIT 2/2019: ngModel together with reactive forms are now also luckily not allowed since v7. That is in my opinion good, since it was misused way too much!
So build your form and attach a custom validator. In case you have a large form, I would attach the custom validator to a nested group of your dates, as it sits in this example, the validator is firing whenever there is any change in the form, doesn't matter if it's the date fields, or some other field.
constructor(private formBuilder: FormBuilder) {
this.unavailabilityForm = this.formBuilder.group({
startDate: [''],
endDate: ['']
}, {validator: this.checkDates});
}
If you are getting your values for variable unavailability
at a later stage, you can use patchValue
or setValue
to assign the values to your form controls:
this.unavailabilityForm.setValue({
startDate: this.unavailability.startDate;
endDate: this.unavailability.endDate;
})
The custom validator simply checks that the end date is a later date than the startdate and returns null
if it is valid, or then a custom validation error:
checkDates(group: FormGroup) {
if(group.controls.endDate.value < group.controls.startDate.value) {
return { notValid:true }
}
return null;
}
and then you can display this custom error in template with:
<small *ngIf="unavailabilityForm.hasError('notValid')">Not valid</small>
Also remember to mark this formgroup in your form tag:
<form [formGroup]="unavailabilityForm">