I am facing a challenge with disabling certain dates on a Material Calendar. These dates are sourced from two different places. The first set of dates come from within an object (camper) that is provided as input. The second set comes from an API call that retrieves a list of bookings based on the camper ID. While the first set of dates is read and disabled without any issues, the problem arises when dealing with the API call. It seems like the filter does not wait for the data to be fully fetched before applying the disabling logic. I have tried various methods such as promises, async/await, and fork join but none seem to make the filter wait or disable any dates at all.
For the specific camper in question, the expected outcome would be 2 periods of disabled dates on the calendar:
- 12/06 to 15/06 (blocked dates) <- visible
- 21/06 to 24/06 (booked dates) <- not visible
I need assistance in finding a way for the filter to wait until the complete list of dates is obtained before applying the disable functionality.
component.html
<div class="calendar-wrapper">
<mat-calendar
#calendar
(monthSelected)="handleMonthSelected($event)"
(selectedChange)="onSelect($event)"
[comparisonStart]="this.selectedDateRange.start"
[comparisonEnd]="this.selectedDateRange.end"
[selected]="selectedDateRange"
[dateFilter]="blockedDatesFilter"
>
</mat-calendar>
</div>
component.ts
export class CamperBookingDetailsComponent implements AfterContentInit {
@Input() camper!: Camper;
@ViewChild('calendar') calendar!: MatCalendar<Date>;
blockedDates = (): Date[] => {
let tempBlockedDates: Date[] = [];
Object.entries(this.camper.difPrizes).forEach(([key, value]) => {
if (value === 0) {
tempBlockedDates.push(new CamperDate(new Date(key)));
}
});
this._bookingService.getBookings$({"camperId": this.camper._id}).subscribe(bookings => {
bookings.forEach(booking => {
this.getDates(new Date(booking.startDate), new Date(booking.endDate)).forEach(date => {
tempBlockedDates.push(date);
});
});
});
return tempBlockedDates;
}
blockedDatesFilter = (d: Date): boolean => {
console.log(this.blockedDates());
const time = d.getTime();
return !this.blockedDates().find(x => x.getTime() == time);
};
constructor(private _renderer: Renderer2, private _bookingService: BookingService) {}
}
I also attempted using asynchronous code like below. However, it was unsuccessful as the Material Calendar does not support (d: Date) => Promise.
blockedDates = async (): Promise<Date[]> => {
let tempBlockedDates: Date[] = [];
Object.entries(this.camper.difPrizes).forEach(([key, value]) => {
if (value === 0) {
tempBlockedDates.push(new CamperDate(new Date(key)));
}
});
await this._bookingService.getBookings$({"camperId": this.camper._id}).subscribe(bookings => {
bookings.forEach(booking => {
this.getDates(new CamperDate(booking.startDate), new CamperDate(booking.endDate)).forEach(date => {
tempBlockedDates.push(date);
});
});
});
return tempBlockedDates;
}
blockedDatesFilter = async (d: Date): Promise<boolean> => {
console.log(this.blockedDates());
const time = d.getTime();
const blockedDates = await this.blockedDates();
return !blockedDates.find(x => x.getTime() == time);
};
Console log excerpt from within
blockedDatesFilter = (d: Date): boolean
:
(4) [Sun Jun 12 2022 00:00:00 GMT+0200 (Central European Summer Time), Mon Jun 13 2022 00:00:00 GMT+0200 (Central European Summer Time), Tue Jun 14 2022 00:00:00 GMT+0200 (Central European Summer Time), Wed Jun 15 2022 00:00:00 GMT+0200 (Central European Summer Time)]
0: Sun Jun 12 2022 00:00:00 GMT+0200...
Material Calendar Screenshot: Material Calendar