Reputation: 51
I have 3 date picker fields, contractPeriodFrom, contractPeriodTo and dateOfAppointment. The dateOfAppointment should be between the contractPeriodFrom and contractPeriodTo. I am unsure how to do this as both contractPeriod fields are form controls.
<div fxLayout="row">
<mat-form-field fxFlex="50">
<input matInput [matDatepicker]="picker2" formControlName="contractPeriodFrom" readonly>
<mat-datepicker-toggle matSuffix [for]="picker2"></mat-datepicker-toggle>
<mat-datepicker #picker2></mat-datepicker>
</mat-form-field>
<mat-form-field fxFlex="50">
<input matInput [matDatepicker]="picker3" formControlName="contractPeriodTo" readonly>
<mat-datepicker-toggle matSuffix [for]="picker3"></mat-datepicker-toggle>
<mat-datepicker #picker3></mat-datepicker>
</mat-form-field>
</div>
<div fxLayout="row" class="mt-16">
<mat-form-field fxFlex="50">
<input matInput [matDatepicker]="picker1" formControlName="dateOfAppointment" readonly>
<mat-datepicker-toggle matSuffix [for]="picker1"></mat-datepicker-toggle>
<mat-datepicker #picker1></mat-datepicker>
</mat-form-field>
</div>
The form fields are part of a form group and initialized as below -
this.lieUpdateForm = this._formBuilder.group({
dateOfAppointment: [this.selectedLIE.dateOfAppointment || ''],
contractPeriodFrom: [this.selectedLIE.contractPeriodFrom || ''],
contractPeriodTo: [this.selectedLIE.contractPeriodTo || ''],
});
Upvotes: 3
Views: 13080
Reputation: 29
The accepted answer has one flaw though, when using matDateFilter the performance is affected badly. I know the logic in filterFunction is written in such as way that it must be executed minimum times but what if first date isn't provided and user want to make year disabled when false is returned looks like it recursively check for internal dates as well which makes it to get executed lots of times
Upvotes: 0
Reputation: 4819
Have a look here https://material.angular.io/components/datepicker/overview#date-validation. There are two solutions min/max
or matDatepickerFilter
. I would suggest you to use the matDatepickerFilter
one, being cleaner , more flexible and not requiring subscriptions to valueChanges
.
matDatepickerFilter
Add the [matDatepickerFilter]
binding to the input:
<input matInput
[matDatepicker]="picker1"
formControlName="dateOfAppointment" readonly
[matDatepickerFilter]="dateFilter"
>
Then add a validation function to your component (note that is a lambda and not a member function, read more here MatDatepickerFilter - Filter function can't access class variable)
public dateFilter = (d: Date): boolean => {
const value = this.lieUpdateForm.value;
return (d >= this.toDate(value.contractPeriodFrom)) && (d <= this.toDate(value.contractPeriodTo));
}
min/max
Add the [min]
and [max]
binding to the input:
<input matInput
[matDatepicker]="picker1"
formControlName="dateOfAppointment" readonly
[min]="minDate" [max]="maxDate"
>
Then after right after assigning lieUpdateForm
add:
this._subscription = this.lieUpdateForm
.valueChanges.subscribe(value => {
this.minDate = toDate(value.contractPeriodFrom);
this.maxDate = toDate(value.contractPeriodTo);
});
Do not forget to clear _subscription
onDestroy
toDate
toDate
is a function that makes sure we are dealing with Date objects. According to the documentation it should work just fine without it. I added it just in case. This is the implementation if needed:
protected toDate(d: Date | string): Date {
return (typeof d === 'string') ? new Date(d) : d;
}
Upvotes: 4
Reputation: 2112
<input matInput [min]="minDate" [max]="maxDate" [matDatepicker]="picker" placeholder="Choose a date">
Then you can set the Value for maxDate and minDate in ts file
this.lieUpdateForm.get("dateOfAppointment").valueChanges.subscribe(selectedValue => {
console.log('dateOfAppointment value changed')
console.log(selectedValue) //latest value of dateOfAppointment
console.log(this.lieUpdateForm.get("dateOfAppointment").value) //latest value of dateOfAppointment
})
Upvotes: 0