【问题标题】:How can I catch the Material Datepicker month pagination event?如何捕捉 Material Datepicker 月份分页事件?
【发布时间】:2019-08-15 13:00:53
【问题描述】:

我想捕捉来自月份“左”和“右”选择按钮的事件,但我找不到任何有关它的文档。

在 Material Datepicker 中单击“左”和“右”月份选择框时会触发哪些事件?

【问题讨论】:

  • 您最初写的问题不够详细,以至于有人在没有看到该外部链接的情况下跟踪正在发生的事情。我已经对其进行了编辑并将图像添加到问题中;以后在创建问题时请牢记这一点。
  • 看起来你可以绑定一个通用事件,当这些按钮被更改时也可能触发:MatDatepickerInputEvent。 material.angular.io/components/datepicker/api

标签: angular angular-material


【解决方案1】:

好吧,我的另一个回答是错误的,让我们再采取另一种方法。 假设我们有一个 CustomTemplate Header。我们希望它看起来像原始的 DatePicker 标头,我们将复制 gitHub of angular 中的模板,但我们将更改按钮 next 和 prev 中的功能,所以就像

<div class="mat-calendar-header">
  <div class="mat-calendar-controls">
    <button mat-button type="button" class="mat-calendar-period-button"
            (click)="currentPeriodClicked()" [attr.aria-label]="periodButtonLabel"
            cdkAriaLive="polite">
      {{periodButtonText}}
      <div class="mat-calendar-arrow"
           [class.mat-calendar-invert]="calendar.currentView != 'month'"></div>
    </button>

    <div class="mat-calendar-spacer"></div>

    <ng-content></ng-content>

                <!--see that we change previousClicked by customPrev-->
    <button mat-icon-button type="button" class="mat-calendar-previous-button"
            [disabled]="!previousEnabled()" (click)="customPrev()"
            [attr.aria-label]="prevButtonLabel">
    </button>

                <!--see that we change nextClicked by customNext-->
    <button mat-icon-button type="button" class="mat-calendar-next-button"
            [disabled]="!nextEnabled()" (click)="customNext()"
            [attr.aria-label]="nextButtonLabel">
    </button>
  </div>
</div>  

现在我们定义了从 MatCalendarHeader 扩展而来的 customHeader

export class ExampleHeader extends MatCalendarHeader<any> {

  /** Handles user clicks on the period label. */
  currentPeriodClicked(): void {
    this.calendar.currentView = this.calendar.currentView == 'month' ? 'multi-year' : 'month';
  }

  /** Handles user clicks on the previous button. */
  customPrev(): void {
    console.log(this.calendar.activeDate)
    this.previousClicked()
  }

  /** Handles user clicks on the next button. */
  customNext(): void {
    console.log(this.calendar.activeDate)
    this.nextClicked()
  }

那么,只说使用这个ExampleHeader

<mat-form-field>
  <mat-label>Custom calendar header</mat-label>
  <input matInput [matDatepicker]="picker">
  <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
  <mat-datepicker #picker [calendarHeaderComponent]="exampleHeader"></mat-datepicker>
</mat-form-field>

stackblitz

【讨论】:

    【解决方案2】:

    还有一个解决方法是使用 dateClass

    @ViewChild('picker',{static:false}) calendar: MatDatepicker<any>;
      setClass() {
        return (date: any) => {
          if (date.getDate() == 1) this.changeMonth(
             {month:date.getMonth()+1,
              year:date.getFullYear()
              });
        };
      }
    
      changeMonth(date)
      {
        console.log(date)
      }
    

    你在哪里

     <mat-form-field>
      <mat-label>Choose a date</mat-label>
      <input matInput [matDatepicker]="picker">
      <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
      <mat-datepicker #picker [dateClass]="setClass()"></mat-datepicker>
    </mat-form-field>
    

    stackblitz

    好吧,如果没有充分的理由,没有人有兴趣知道月份何时更改。典型的原因是调用了一个 API,该 API 返回一个包含“特殊”天数并显示在日历中的数组。

    要改变这个特殊日子的方面,我们可以认为我们可以使用自己的函数 dateClass 但请记住,我们正在寻找函数执行后的日子 (*)。所以我们需要使用 Renderer2 来添加类。

    如果我们收到的数据有点像(看到“天”是一个字符串)

      [
        {day:'2020-02-06',data:'one'},
        {day:'2020-02-16',data:'two'},
        {day:'2020-02-22',data:'three'}
      ]
    

    我们的函数changeMonth变成这样:

    changeMonth(date) {
        this.dataService.getData(date.month, date.year).subscribe(res => {
          setTimeout(() => {
            let elements = document.querySelectorAll(".calendar");
            if (elements && elements.length) {
              const cells = elements[0].querySelectorAll(".mat-calendar-body-cell");
              cells.forEach(x => {
                const date = new Date(x.getAttribute("aria-label"));
                const dateTxt =
                  date.getFullYear() +
                  "-" +
                  ("00" + (date.getMonth() + 1)).slice(-2) +
                  "-" +
                  ("00" + date.getDate()).slice(-2);
    
                if (res.find(x => x.day == dateTxt))
                {
                  this.renderer.addClass(x, "special");
                }
              });
            }
          });
        });
      }
    

    (*) 我们也可以在 ngOnInit 中查询“特殊日子”,然后简单地使用 dateClass 函数

    【讨论】:

      【解决方案3】:

      在你的 component.ts 中,监听你的 mat-calendar 下一个/上一个按钮上的点击事件。 mat-calendar 按钮的一个唯一标识符可能是 ariaLabel。

        @HostListener('click', ['$event'])
        onClick(event: any) {
          // get the clicked element
          if (event.target.ariaLabel && event.target.ariaLabel.includes("Previous month")) {
            console.log('previous');
          } else if (event.target.ariaLabel && event.target.ariaLabel.includes("Next month")) {
            console.log('next');
          }
        }

      【讨论】:

      • 谢谢!这比自定义日历的标题更简单
      【解决方案4】:

      我发现的唯一方法是(来自onthecode 的想法)在打开状态下,检查querySelectorAll 按钮。有些喜欢

      <mat-form-field>
        <input matInput [matDatepicker]="picker" placeholder="Choose a date">
        <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
        <mat-datepicker #picker (opened)="openCalendar()">
        </mat-datepicker>
      </mat-form-field>
      
        constructor(private renderer: Renderer2) { }
        openCalendar() {
          setTimeout(() => {
            const buttons = document.querySelectorAll
            ('.mat-calendar-previous-button,.mat-calendar-next-button')
            if (buttons) {
              Array.from(buttons).forEach(button => {
                this.renderer.listen(button, "click", (event) => {
                  console.log('Arrow button clicked')
                });
              })
            }
          })
        }
      

      stackblitz

      【讨论】:

      • 谢谢!我也发现了这一点,问题是我无法“检索”我点击的月份,只有我点击了按钮。
      • @KissGábor,只需添加另一种解决问题的方法。我希望这对你有帮助:)
      【解决方案5】:

      在模板上:

      <mat-datepicker #picker (opened)="initEvents()"></mat-datepicker>
      

      当日期选择器打开时添加一个事件监听器并将点击事件添加到按钮...

      TS:

      initEvents(): void {
      setTimeout(() => {
        const prev = document.querySelector('.mat-calendar-previous-button');
        const next = document.querySelector('.mat-calendar-next-button');
        prev.addEventListener('click', () => { // Previous Button
          console.log('Prev');
        });
        next.addEventListener('click', () => { // Next Button
          console.log('Prev');
        });
      
      }, 150);
      

      }

      希望它有效:)

      没有小的延迟,它会显示一个空引用,无论如何,如果有小的延迟,它应该可以正常工作,无论如何,当用户通过动画点击该日期选择器时会有延迟......

      顺便说一句:它显示 null 是因为事件发生在元素(我们的按钮)在 DOM 中之前...

      编辑:这个解决方案的另一件事可能不是最好的,因为每次打开日期选择器时都会注册事件,但它是我发现的最好和最快的方法,一个更好的方法是创建一个自定义标题...但是要编写很多代码..,如果您愿意,可以在官方文档中查看。

      【讨论】:

      • monthSelected 事件在日期选择器的另一部分,当你点击年份,然后选择另一年和一个月
      • sry 稍后回复,我好像错过了理解你,我在 1.5 小时后寻找解决方案,我找到了一个但看起来它显示错误,所以这是我的解决方案。看看编辑过的帖子。
      • 谢谢!我也发现了这一点,问题是我无法“检索”我点击的月份,只有我点击了按钮。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-13
      • 2019-03-01
      相关资源
      最近更新 更多