Multiple Date Select in Material datePicker (Angul

2020-03-31 08:11发布

I have a requirement that a user can select multiple dates in a date picker. How can I implement multiple date select functionality in an Angular Material date picker?

date picker

I tried this through dateClass. But, after every date selection the date picker will be closed.

Here's what I tried

HTML code:

<input matInput [matDatepicker]="picker" placeholder="Choose a date">
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
<mat-datepicker [dateClass]="dateClass" #picker></mat-datepicker>

Typescript code:

dateClass = (d: Date) => {
    const date = d.getDate();

    // Highlight the 1st and 20th day of each month.
    return (date === 1 || date === 5 || date === 14 || date === 19 || date === 21 ) ? 'example-custom-date-class' : undefined;
}

2条回答
淡お忘
2楼-- · 2020-03-31 08:32

One more way (kinda hack): StackBlitz

Just temporary rewriting close method to empty function, and return it back after change. Also calling weekdays rerendering function. Not safe and ideal solution, but works.

Might be useful for somebody.

查看更多
别忘想泡老子
3楼-- · 2020-03-31 08:36

You need work directly with the mat-calendar, you can enclosed in a mat menu and into a div to avoid "closed", see

<button mat-icon-button [matMenuTriggerFor]="appMenu">
  <mat-icon>calendar_today</mat-icon>
</button>
<mat-menu #appMenu="matMenu">
    <div (click)="$event.stopPropagation()">
        <mat-calendar #calendar 
           (selectedChange)="select($event,calendar)" 
            [dateClass]="isSelected">
        </mat-calendar>
    </div>
</mat-menu>

I choose store the values of the dates in a string in the way yyyy-MM-dd (*), so

Imports:

import { Component,ViewEncapsulation} from "@angular/core";

TS Code:

daysSelected: any[] = [];
event: any;

isSelected = (event: any) => {
  const date =
    event.getFullYear() +
    "-" +
    ("00" + (event.getMonth() + 1)).slice(-2) +
    "-" +
    ("00" + event.getDate()).slice(-2);
  return this.daysSelected.find(x => x == date) ? "selected" : null;
};

select(event: any, calendar: any) {
  const date =
    event.getFullYear() +
    "-" +
    ("00" + (event.getMonth() + 1)).slice(-2) +
    "-" +
    ("00" + event.getDate()).slice(-2);
  const index = this.daysSelected.findIndex(x => x == date);
  if (index < 0) this.daysSelected.push(date);
  else this.daysSelected.splice(index, 1);

  calendar.updateTodaysDate();
}

Finally the .css is simple:

.mat-calendar-body-cell.selected
{
  background-color:red!important;
  border-radius: 50%
}
.drop-calendar
{
  width:30rem
}

NOTE: Dont forget to set encapsulation to none in your component:

encapsulation:ViewEncapsulation.None

You can see in stackblitz

(*) you can choose, e.g. store the getTime() of the date selected. The idea is that you need find it in the array "daysSelected", else, if you use directy an object Date, you need compare year, month and day from date to the elements of the array. This give a poor perfomance. Think that the function "isSelected" is called how many times as days has a month, each time a click is done

查看更多
登录 后发表回答