【问题标题】:Angular Material Datepicker with Range Selection具有范围选择的角材料日期选择器
【发布时间】:2020-02-16 11:24:02
【问题描述】:

我正在使用 Angular 8,我想实现一个突出显示日期的日期选择器: enter image description here 我正在寻找这样的包裹:https://www.npmjs.com/package/saturn-datepicker 不幸的是,它已被弃用,目前我找不到其他类似的。 你知道我的目的吗?谢谢你。

【问题讨论】:

    标签: angular datepicker angular-material


    【解决方案1】:

    重要更新,天哪!谷歌有很多像我一样的控件! (记住:谷歌是我的朋友,谷歌是我的朋友……)

    我在 stackblitz 中创建了一个 datePicker 范围,我会在之后尝试解释

    更新我改进了stackblitz和一个简短的解释

    mat-date-picker 有一点很重要,那就是不可能创建日期模板。所以需要使用 Renderer2 来添加监听器、添加类或移除类。我需要使用this another SO中显示的 document.querySelectorAll

    想法是,通过选定的单元格创建一个对象数组

    {
       date: //will be a getTime of the date,
       element: //will be the nativeElement x,
       change: //a boolean to indicate this cell has an aditional class
       x.listen: //the listener added to allow us remove the listener
    }
    

    还有一个函数可以帮助我们根据两个变量添加/删除类:this._dateTo 和另一个变量 this._dateFrom 或另一个变量(我们很早就发现了原因)

      redrawCells(timeTo: number) {
        timeTo = timeTo || this._dateTo;
        if (timeTo<this._dateFrom)
          timeTo=this._dateFrom
        this.cells.forEach(x => {
          const change = x.date >= this._dateFrom && x.date <= timeTo;
          if (change || x.change) {
            x.change = change;
            const addInside = x.change ? "addClass" : "removeClass";
            const addFrom = x.date == this._dateFrom? "addClass":
                            x.date == timeTo && this._dateFrom==timeTo? "addClass":
                            "removeClass";
            const addTo = x.date == timeTo? "addClass": 
                          x.date == this._dateFrom && this._dateFrom==timeTo? "addClass":
                            "removeClass";
    
            this.renderer[addInside](x.element, "inside");
            this.renderer[addFrom](x.element, "from");
            this.renderer[addTo](x.element, "to");
          }
        });
      }
    

    一个新的函数 setCell 将负责管理 td 以添加/删除鼠标悬停的侦听器。它必须包含在 setTimeout 中,因为我们在绘制日历之前调用此函数

      setCells() {
        setTimeout(() => {
          if (this.cells) {
            this.cells.forEach(x => {
              x.listen();  //<---remove the listener
            });
          }
          this.dateOver = null;
          //get the elements
          let elements = document.querySelectorAll(".calendar");
          if (!elements || elements.length == 0) return;
          const cells = elements[0].querySelectorAll(".mat-calendar-body-cell");
          this.cells = [];
          //with each element we fill our array "this.cells"
          cells.forEach((x, index) => {
            const date = new Date(x.getAttribute("aria-label"));
            const time=new Date(date.getFullYear() +"-" +(date.getMonth() + 1) +
                  "-" +date.getDate()).getTime()
    
            this.cells.push({
              date: time,
              element: x,
              change:time>=this._dateFrom && time<=this._dateTo
            });
          });
          this.cells.forEach(x => {
            if (!x.listen) {
              //we add a listener "mouseover"
              x.listen = this.renderer.listen(x.element, "mouseover", () => {
                if (!this._dateTo && this.dateOver != x.date) {
                  this.dateOver = x.date;
                  this.redrawCells(this.dateOver); //who call to redrawCells
                }
              });
            }
          });
        });
      }
    

    好吧,解析和格式化日期以及使用 mat-menu 打开 mat-calendar 所需的其余函数来自 this another SO。在最后一个 SO 中,日历没有关闭,因此,我们可以使用强制两次单击来获取 dateFrom 和 dateTo

      select(date: any) {
        date = new Date(
          date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate()
        );
        if (
          !this.from.value ||
          (this.from.value && this.to.value) ||
          this._dateFrom > date.getTime()
        ) {
          this.dateFrom = date;
          this.dateTo = null;
          this.redrawCells(date.getTime());
        } else {
          this.dateTo = date;
          this.trigger.closeMenu();
        }
      }
    

    我喜欢创建一个 mat 自定义组件。这允许我们在 mat-form-field 中使用组件,有些像

    <mat-form-field class="full-width" >
      <mat-label>Select dates</mat-label>
      <date-picker-range [formControl]="control" placeholder="DD/MM/YYYY"  ></date-picker-range>
      <mat-error>required</mat-error>
    </mat-form-field>
    

    并允许例如我们使用 [disabled] 来禁用 formControl,并且标签像另一个 mat-input 一样移动。为此我们需要添加一些功能,请参阅(我保证这是最后一个)last recent SO

    注意:控件是“原样”,没有任何保证,并且是允许的:批评、改进、修改、使用或将其作为坏例子

    【讨论】:

      【解决方案2】:

      在材料日期选择器中,您可以定义最大值和最小值。

      例如:

      example.hml <input matInput [min]="minValue" [max]="maxValue" [matDatepicker]="picker" formControlName="name"/> <mat-datepicker #voltageToDatePiker [startAt]="tomorrow"></mat-datepicker>

      example.ts minValue = new Date(); maxValue = new Date();

      【讨论】:

        【解决方案3】:

        在角度材料中,有一个选项可以指定范围 https://material.angular.io/components/datepicker/overview#date-range-selection

        <mat-form-field appearance="fill">
          <mat-label>Enter a date range</mat-label>
          <mat-date-range-input [rangePicker]="picker">
            <input matStartDate placeholder="Start date">
            <input matEndDate placeholder="End date">
          </mat-date-range-input>
          <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
          <mat-date-range-picker #picker></mat-date-range-picker>
        </mat-form-field>
        

        https://stackblitz.com/angular/pydjpbqmvqq?file=src%2Fapp%2Fdate-range-picker-overview-example.html

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-09-13
          • 2018-04-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多