Search code examples
angularangular-materialdatepicker

Multiple dateRange filter for Angular Material DatePicker


i have a multiple startDate and endDate from my data and i want to use that for disabled date range in datePicker Material of Angular.

I see this issue :link, but in the example is for two table, in my case i have a lot of table, so i begin a code with a loop but i don't know how to use it

this is my code :

import { formatDate } from '@angular/common';
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { map, Observable } from 'rxjs';
import { Booking } from 'src/app/core/models/booking.model';
import { BookingService } from 'src/app/core/services/booking.service';

@Component({
  selector: 'app-booking',
  templateUrl: './booking.component.html',
  styleUrls: ['./booking.component.scss'],
})
export class BookingComponent implements OnInit {
  idAccommodation!: number;
  bookingAccommodation$!: Observable<Booking[]>;
  dateBooking: Array<Array<any>> = [];
  dateDisabled!: any;

  constructor(
    private activedRoute: ActivatedRoute,
    private bookingService: BookingService
  ) {}

  ngOnInit(): void {
    this.idAccommodation = +this.activedRoute.snapshot.params['id'];
    this.bookingService
      .getBookingByIdAccommodation(this.idAccommodation)
      .pipe(map((res: any) => res['hydra:member']))
      .subscribe({
        next: (res: any) => {
          res.forEach((element: any) => {
            this.dateBooking.push([
              new Date(element.startDate),
              new Date(element.endDate),
            ]);
          });

          this.dateBooking.forEach((element) => {
            element.forEach((date) => {
              console.log(date);
            });
          });

          this.dateDisabled = (date: Date | null): any => {
            return (
              !(
                date! >= this.dateBooking[1][0] &&
                date! <= this.dateBooking[1][1]
              ) && date! >= new Date()
            );
          };
        },
      });
  }
}

Thanks for your helping 👍


Solution

  • When you work with Date javascript object you need be carefull

    A mat-datepicker return you a date object of type, e.g.

    Mon Sep 19 2022 00:00:00 GMT+0200
    

    When you use, e.g.

    new Date('2022-08-24')
    //you get
    Date Wed Aug 24 2022 02:00:00 GMT+0200
    

    See how add the "02:00:00" -because I'm in GTM+0200. So the first you need is that your range becomes in the way 00:00:00 using setHours

    res.forEach((element: any) => {
       const el=[
              new Date(element.startDate),
              new Date(element.endDate),
            ]
            el[0].setHours(setHours(0, 0, 0, 0))
            el[1].setHours(setHours(0, 0, 0, 0))
            this.dateBooking.push(el);
          });
    }
    

    Equal you need take carefull with "today". So in ngOnInit you can use

      ngOnInit() {
    
        //see how use setHours also in today
        const today = new Date();
        today.setHours(0, 0, 0, 0);
    
        this.dateDisabled = (date: Date | null): any => {
          if (date! < today) return false;
          for (let i = 0; i < this.dateBooking.length; i++) {
            if (date! >= this.dateBooking[i][0] && date! <= this.dateBooking[i][1])
              return false;
          }
          return true;
        };
    
        //or
    
        this.dateDisabled = (date: Date | null): any => {
          return (
            date! >= today &&
            this.dateBooking.reduce((a, b) => {
              return a && (date! < b[0] || date! > b[1]);
            }, true)
          );
        };
      }
    

    NOTE: the second approach loop over all the elements of dateBooking. It's looks like slower that the first one but really the time spend (30 days* dateBooking.length) it's not apreciable

    see stackblitz

    NOTE2: If you need severals "dateDisabled" functions use an array of functions

    dateDisabled:((date: Date | null)=>any)[]=[]
    
    //  and use 
    dateDisabledObj[index]=(date: Date | null): any => {...}
    

    Or and object of functions

    dateDisabledObj:any={}
    
    // and use 
    dateDisabledObj[''+id]=(date: Date | null): any => {...}