【问题标题】:How to highlight custom months and years in Angular Material datepicker?如何在Angular Material datepicker中突出显示自定义月份和年份?
【发布时间】:2020-11-08 19:30:56
【问题描述】:

我有一系列日期,可以是任何年份。 我正在尝试自定义 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 月份如果 2020 年被选中,然后在 红色边框 中突出显示 MAY & AUG,当前月份和年份除外,如下图所示。

这可能吗?

我搜索了很多并尝试使用 dateClass、(yearSelected) 事件等,但它不适用于 Months 和 Years.. 如果有人知道,请帮助..

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

【问题讨论】:

    标签: html css angular typescript mat-datepicker


    【解决方案1】:

    控制材质角度日期选择器事件确实有点复杂。我不知道是否有更好的方法,但是您可以使用自定义标头组件来获取它,请参阅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 和组件中注入 dataService 后,在 Example 头中是一个复杂的但它只是写入

      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看到

    更新如果只想“备注”月份,事情就更简单了,因为我们只需要控制(yearSelected)事件,就可以忘记自定义标题了。

    <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

    【讨论】:

    • 非常感谢...
    • 我的案例有点类似但更简单。在显示日历时,如何仅突出显示月份?例如,六月、七月、八月。
    • @ahkeno,肯定更简单,你只需要控制 (yearSelected) 事件。此外,您可以使用 index="yearSelected($event)",查看更新后的答案
    • 当然,你只需要调用(opened)中的函数即可。注意:放一个“if”来检查 calendar.view=="year",我刚刚更新了 stackblitz
    • stackblitz 它只是如何“标记”基于月份数组的月份(当然你可以更改月份数​​组而不是在“硬代码”中使用,例如你可以有一个可变月份并使用本月和下一个月创建数组,或者具有两个变量 fromMonth 和 toMonth 并更改条件),但是范围月更复杂。在材料角度允许日期选择器范围之前,我写了这个 SO:stackoverflow.com/questions/60247962/… - 这只是几天的日期选择器范围 - 但可以作为灵感
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-16
    • 1970-01-01
    • 2020-02-26
    • 2018-07-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多