如何在 Angular Material 日期选择器中突出显示自定义月份和年份?

How to highlight custom months and years in Angular Material datepicker?

我有一组天数,可以是任何一年。 我正在尝试自定义 Angular Material 日期选择器以突出显示月份选择视图中的某些月份,以及基于天数数组的年份选择视图中的某些年份。

.html

<input [matDatepicker]="picker" />
<i class="fas fa-chevron-down"></i>
<mat-datepicker #picker></mat-datepicker>

.ts

arrayOfDays = [new Date('2019-01-01'), new Date('2020-08-10'),  new Date('2020-09-20')];

我想要实现的是 在年视图中突出显示 2019 年和 2020 年如果选择 2019 年,则突出显示 JAN 月[=39] =] 和 如果选择 2020,则在 红色边框 中突出显示 MAY & AUG 除了当前月份和年份,如下图所示。

这可能吗?

我搜索了很多并尝试使用 dateClass、(yearSelected) 事件等,但它不适用于月份和年份。如果有人知道如何做到这一点,请帮助..

仅供参考 - https://stackblitz.com/edit/angular-date-class-filter-aactjv 这是我发现的将自定义设计设置为日期视图的那个。但是我想要年和月视图的类似实现。 提前致谢..

确实,控制 material angular 日期选择器事件有点复杂。我不知道是否有更好的方法,但您可以使用自定义 header 组件来获取它,请参阅此 SO

之前,我们要创建一个dataService

@Injectable({
  providedIn: "root"
})
export class DataService {
  arrayOfDays = [
    new Date("2019-01-01"),
    new Date("2020-08-10"),
    new Date("2020-09-20")
  ];

  constructor() {}
  displayMonth(year: number, view: string) {
    setTimeout(() => {
      let elements = document.querySelectorAll(".mat-calendar-content");
      let x = elements[0].querySelectorAll(".mat-calendar-body-cell-content");
      if (view == "multi-year") {
        const years = this.arrayOfDays.map(x => x.getFullYear());
        x.forEach((y: any) => {
          if (years.indexOf(+y.innerHTML) >= 0) {
            {
              y.style["border-color"] = "red";
            }
          }
        });
      }
      if (view=="year"){
        const monthsIni = [
          "JAN","FEB","MAR","APR","MAY","JUN","JUL","AUG","SEP","OCT","NOV","DEC"
        ];
        const months = this.arrayOfDays
          .filter(x => x.getFullYear() == year)
          .map(x => monthsIni[x.getMonth()]);
        x.forEach((y: any) => {
          if (months.indexOf(y.innerHTML) >= 0) {
            {
              y.style["border-color"] = "red";
            }
          }
        });
      }
    });
  }
}

在 ExampleHeader 和组件中注入数据服务后,在示例中 header 是一个 fwe 复合体,但它只是 write

  constructor(_intl: MatDatepickerIntl,
              @Inject(forwardRef(() => MatCalendar)) calendar: MatCalendar<any>,
              @Optional() _dateAdapter: DateAdapter<any>,
              @Optional() @Inject(MAT_DATE_FORMATS) _dateFormats: MatDateFormats,
              changeDetectorRef: ChangeDetectorRef
              ,private dataService:DataService
              ) {
    super(_intl,calendar,_dateAdapter,_dateFormats,changeDetectorRef)
  }

当处理用户点击期间标签时,用户点击上一个按钮,用户点击下一个按钮调用服务

  currentPeriodClicked(): void {
    this.calendar.currentView =
      this.calendar.currentView == "month" ? "multi-year" : "month";
    this.dataService.displayMonth(
      this.calendar.activeDate.getFullYear(),
      this.calendar.currentView
    );
  }

  customPrev(): void {
    this.previousClicked();
    this.dataService.displayMonth(
      this.calendar.activeDate.getFullYear(),
      this.calendar.currentView
    );
  }

  customNext(): void {
    this.nextClicked();
    this.dataService.displayMonth(
      this.calendar.activeDate.getFullYear(),
      this.calendar.currentView
    );
  }

此外我们还需要在主组件中选择它

  yearSelected(event: any) {
    this.dataService.displayMonth(
      event.getFullYear(),
      this.calendar.currentView
    );
  }

您可以在stackblitz

中看到

Update 如果只想“备注”月份,事情就简单多了,因为我们只需要控制(yearSelected)事件,就可以不用管了习俗 header.

<mat-datepicker #picker [dateClass]="dateClass"
 (yearSelected)="yearSelected($event)"  
 [calendarHeaderComponent]="exampleHeader">
</mat-datepicker>

months = [0,3] //<--in a variable the months we want remark

yearSelected(event:any)
  {
    setTimeout(()=>{
        let elements = document.querySelectorAll(".mat-calendar-content");
        let x = elements[0].querySelectorAll(".mat-calendar-body-cell-content");
        x.forEach((y: any,month:number) => {
          if (this.months.indexOf(month) >= 0) {
            {
              y.style["border-color"] = "red";
            }
          }
        });
      }
    )
  }

stackblitz