Search code examples
angulardatepickerangular-materialdisabled-input

How to disable Angular Material Datepicker dates from an array of dates?


I have an array of Dates that I call holidayList that I'd like to disable using Angular Material's Datepicker.

    holidayList: Date[] = [];
        this.holidayList: [
                    new Date("1/1/2020"),
                    new Date("1/20/2020"),
                    new Date("2/17/2020"),
                    new Date("5/25/2020"),
                    new Date("7/4/2020"),
                    new Date("9/7/2020"),
                    new Date("10/12/2020"),
                    new Date("11/11/2020"),
                    new Date("11/26/2020"),
                    new Date("12/25/2020")
                ]

Reading Angular's Date validation documentation, we can utilize [matDatepickerFilter]="myFilter" like so:

HTML:

<mat-form-field class="example-full-width">
  <input matInput [matDatepickerFilter]="myFilter" [matDatepicker]="picker" placeholder="Choose a date">
  <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
  <mat-datepicker #picker></mat-datepicker>
</mat-form-field>

TypeScript:

import {Component} from '@angular/core';

/** @title Datepicker with filter validation */
@Component({
  selector: 'datepicker-filter-example',
  templateUrl: 'datepicker-filter-example.html',
  styleUrls: ['datepicker-filter-example.css'],
})

export class DatepickerFilterExample {
  myFilter = (d: Date): boolean => {
    const day = d.getDay();
    // Prevent Saturday and Sunday from being selected.
    return day !== 0 && day !== 6;
  }
}

However, this example provided is essentially saying 'provide all the days where the day of the week is not 0 or 6'. I am a bit confused as to how to implement a list of dates and say 'here are the list of dates we should disable'.

Link to Angular Material's example on Stackblitz

I know there are multiple questions on this topic but all the answers I've come across only address disabling certain days of the week, months (e.g disabling odd months) - essentially disabling a type of day; in this case, I'd like to disable hard-coded dates and nothing more.


Solution

  • Jedo you need change the function myFilter that return true if is valid (in your case if it's not in the array Holiday) and false if is invalid (when the date is in your array Holiday). So you simple replace the function by

      myFilter = (d: Date): boolean => {
        const time=d.getTime()
        return !this.holidayList.find(x=>x.getTime()==time)
      }
    

    NOTE: to find in the array I transform your array of Dates using getTime, it's more effective if you store your arry directitly as time

        this.holidayList=[new Date("1/1/2020").getTime(),
                          new Date("1/20/2020").getTime(),
                          ...  
                         ]
    

    And your function

     myFilter = (d: Date): boolean => {
        const time=d.getTime()
        return !this.holidayList.find(x=>x==time)
      }
    

    NOTE2: (this don't avoid the user can enter a invalid date manually, so you need make a custom validator to check if the date is valid

    validateDate()
    {
       return (control:FormControl)=>{
           const time=control.value.getTime();
           return this.holidayList.find(x=>x==time)?{error:'we are on holidays'}:null
       }
    }