Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I set Min and Max values on a Datepicker field based on two other Datepicker fields - Angular Material

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 || ''],
    }); 
like image 425
gguptha Avatar asked Dec 06 '25 13:12

gguptha


1 Answers

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;
}
like image 81
Newbie Avatar answered Dec 08 '25 06:12

Newbie



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!