Curtis
Curtis

Reputation: 3449

Stylizing specific days from the material datepicker in Angular

Im looking to style specific days in the datepicker object but I cant seem to get access to the DOM elements from the calendar. I tried using a view child, but that only gave me access to the picker element, not the calendar that gets created when click on the picker.

I have also tried adding a panel class to the date picker and trying to select on that, but it also doesnt seem to work. https://stackblitz.com/edit/angular-zjt5wz-ehdbdt?file=app/datepicker-start-view-example.ts

Ideally, I want to apply a class to every day that meets a specific criteria. For example, style all days prior to the selected day as yellow. How can I go about doing this?

Upvotes: 1

Views: 4225

Answers (3)

H S W
H S W

Reputation: 7129

It can be done through css. Here for example I am chsnging the color of dates of the weekends:

.mat-calendar-table {
   td:first-child > .mat-calendar-body-cell-content {
     color: red;
   }
   td:nth-child(7) > .mat-calendar-body-cell-content {
     color: red !important;
   }
}

Upvotes: 0

andreisrob
andreisrob

Reputation: 1715

You are looking for the @Input() dateClass: (date: D) => MatCalendarCellCssClasses property of mat-datepicker. You provide a function that takes a date param and returns a css class. Use the function to decide which dates should have the css class.

Every time the user changes the display, i.e. moves to another month, the function is called for every date in the display.

And finally, you may need to include the css class in a global file and not in the css file associated with your component (research "View Encapsulation" for more).

Upvotes: 3

David
David

Reputation: 34445

That's because when the opened event fires, the view does not contain the DOM elements for the calendar yet.

You can wrap your code in a setTimeout as a workaround

streamOpened(event) {
   setTimeout(()=>{
   let elements = document.querySelectorAll('.endDate');
   //here elements will not be empty
   });

Modified stackblitz

Edit

Following your comment, the material datepicker API has no event for listening to changes to displayed date range. As a hack, you could try manually listening to next/previous button click like this

constructor(private   renderer:Renderer2){}
//...
let nextBtn = document.querySelectorAll('.mat-calendar-next-button')[0];
this.renderer.listen(nextBtn, 'click', ()=>
{
  console.log('click on next')
  //Re-run logic here (probably in timeout again...)
})

Edit 2

Following your 2nd comment, here is an example that binds refresh to all calendar button clicks. That should be enough to get you going. You'll probably need to add more listener to other calendar events though

updated demo

Basically, you can try listening to all click events

let x =  elements[0].querySelectorAll('.mat-calendar-body-cell');
    x.forEach(y => {

      let c = new Date(y.getAttribute("aria-label"));
      if(c < this.startDate)
      {
        y.classList.add('newClass');
      } 
    });

Upvotes: 4

Related Questions