2

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?

Edric
  • 24,639
  • 13
  • 81
  • 91
Stol
  • 179
  • 1
  • 9
  • Can you provide a link to the exact package you're using? Also, if there is not an API available to do what you're doing, you can simple hook into the "open" callback of the datepicker and query the DOM looking for dates with a specific value, and set class on those elements that way. – Lansana Camara Feb 20 '18 at 15:40
  • I'm using the angular material datepicker [link](https://material.angular.io/components/datepicker/overview) , I'm not sure how I would go about hooking into the callback, do you have an example? – Stol Feb 28 '18 at 07:45

3 Answers3

1

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.

Lansana Camara
  • 9,497
  • 11
  • 47
  • 87
  • 2
    Angular Material team provides easier way: https://material.angular.io/components/datepicker/overview#highlighting-specific-dates – Jimmy Lin Feb 09 '19 at 13:22
1

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

Abudy Gold
  • 11
  • 1
1

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.

aw04
  • 10,857
  • 10
  • 56
  • 89