I've been looking around for a way to mark up special days in the calendar to
the user. I know that you can disable certain days in the datepicker but I would
like to be able to just mark/style certain days, for instance change background/color
to red on dates that have a special value, holidays for instance, and not disable them.
I have not found any way to do this, sorry if I have missed something obvious. Have anyone found a way to do this or is it easier to just make my own datepicker in this case?
If you look at the HTML of an open datepicker, you will see each day is represented by a td
, like so:
<td class="mat-calendar-body-cell ng-star-inserted" role="gridcell" tabindex="-1" aria-label="February 4, 2018" style="width: 14.2857%; padding-top: 7.14286%; padding-bottom: 7.14286%;"><div class="mat-calendar-body-cell-content">4</div></td>
What we can derive from that HTML is an aria-label
and a class of mat-calendar-body-cell
.
To achieve what you want, you can use the @Output() openedStream
event. This will be triggered whenever the calendar is opened.
As per the docs: @Output('opened') openedStream: EventEmitter<void>
.
Once you receive the event, you can then query the DOM by the mat-calendar-body-cell
class that has a combination of an aria-label
attribute with a certain date, and if there are matches then you can add a class to those matches.
Let me know if you have any issues with that. But you should be able to follow that rubric step by step to achieve what you want.
For more options from the datepicker API, look at the docs here.
html:
<mat-calendar [minDate]="minDate" [maxDate]="maxDate" [selected]="selectedDates" (selectedChange)="selectedChange($event)" [headerComponent]="displayMonth()" [startAt]="startDate"></mat-calendar>
.ts:
import { Component, OnInit, Input, OnChanges, ViewEncapsulation, ElementRef, Renderer2 } from '@angular/core';
constructor(
private elRef: ElementRef,
private renderer: Renderer2
) {}
displayMonth() {
let HeaderElsClass = this.elRef.nativeElement.getElementsByClassName('mat-calendar-body-cell');
let orderDate = this.convertDate.dateFormat(this.tempOrdersDate, 'MMMM D, YYYY');
// tempOrderDate is epoch array, i convert from epoch to date
for(let index in HeaderElsClass) {
if(typeof HeaderElsClass[index] === 'object') {
let headerClass = HeaderElsClass[index].getAttribute('aria-label');
orderDate.find(each => {
if(each === headerClass) {
this.renderer.addClass(HeaderElsClass[index], 'mat-calendar-body-active');
this.renderer.setStyle(HeaderElsClass[index], 'font-weight', '900');
}
return false;
})
}
}
}
this working fine in my code. i hope work to you.
thanks, Abdullah
mat-datepicker
has a dateClass
input that does exactly this. Pass it a function that accepts a Date
and return a class name to apply.
Example from docs:
<mat-form-field class="example-full-width">
<input matInput [matDatepicker]="picker" placeholder="Choose a date">
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
<mat-datepicker [dateClass]="dateClass" #picker></mat-datepicker>
</mat-form-field>
dateClass = (d: Date) => {
const date = d.getDate();
// Highlight the 1st and 20th day of each month.
return (date === 1 || date === 20) ? 'example-custom-date-class' : undefined;
}
.example-custom-date-class {
background: orange;
border-radius: 100%;
}
Note in my case I had to apply the background to .mat-calendar-body-cell-content
, a direct child of .example-custom-date-class
, rather than to the class directly as in the example.