【问题标题】:Angular-Material DateTime Picker Component?角材料日期时间选择器组件?
【发布时间】:2018-07-16 22:15:42
【问题描述】:

我在一个项目中导入了一个date picker,想知道是否有任何官方最近的组件来自角度和材料,以包括日历中的时间。
我在材料文档中看到了很多时间选择器,并研究了很多第三方,但它们看起来非常复杂。

【问题讨论】:

    标签: angular datepicker angular-material2 datetimepicker timepicker


    【解决方案1】:

    当使用 matInput 类型为 datetime-local 时,您可以有一个日期时间选择器,如下所示:

      <mat-form-field>
        <input matInput type="datetime-local" placeholder="start date">
      </mat-form-field>
    

    您可以单击占位符的每个部分来设置日、月、年、小时、分钟以及是上午还是下午。

    【讨论】:

    • 有没有办法为输入设置语言环境? IE。有dd/mm/yyyy --:-- 24 小时格式?
    • @mohax 检查 material.angular.com 上的示例页面 material.angular.io/components/datepicker/examples 其中一个示例是使用 DateAdapter 对象切换区域设置。也许这就是你要找的。我自己没有任何经验
    • 截至 2019 年 10 月,这在 Chrome 和 MS Edge 上运行良好。截至目前,Firefox 不支持 type="datetime-local"。它只是将其视为常规输入。 caniuse stats
    • 小心,type="datetime-local" 是一个浏览器实现,这不是一个角度材质样式的组件。
    • @mhodges 几乎本周(2021 年 10 月 5 日)。Firefox 支持 type="datetime-local"
    【解决方案2】:

    我建议您结帐@angular-material-components/datetime-picker。 这是一个类似于@angular/material Datepicker 的 DatetimePicker,增加了对选择时间的支持。

    【讨论】:

    • 这个库在支持语言环境方面的文档非常差,并且示例代码中存在重大错误。除非您恰好想要默认设置(以及仅限美国的语言环境),否则几乎无法使用。几个月和几个月前有开放的请求修复,但没有可见的活动。我会避免的。
    • 对于 Angular 8(以及其他旧版本,我怀疑),您必须分叉整个项目并对其进行更正以使其工作...github.com/h2qutc/angular-material-components/issues/53
    【解决方案3】:

    只要 Angular 本身没有官方日期时间选择器,我建议将 default angular date pickerAngular Material Timepicker 组合起来。我之所以选择那个,是因为我此时发现的所有其他问题都缺乏对问题的支持,已经过时或在最新的 Angular 版本中运行不佳。这家伙似乎反应灵敏。

    我将它们都包装在一个组件中,这样看起来就像是一个单元。你只需要确保做几件事:

    如果还没有任何意见,我会建议:

    • 单击组件时,应始终首先触发日期选择器。
    • 日期选择器关闭后,自动弹出时间选择器。
    • 在 datepicker 上使用 touchUi = true,这样 datepicker 和 timepicker 就会作为一个对话框出现。
    • 确保在单击表单时也会显示日期选择器(而不是仅显示在默认的图标上)。
    • 使用this solution 也可以在材质形式中使用时间选择器,将它们放在一起时,看起来就像是一个形式。

    给定一个值后,很明显一部分包含时间,另一部分包含日期。在那一刻,很明显用户必须点击时间来改变时间,点击日期来改变日期。但在此之前,因此当两个字段为空时(并且作为一个字段相互“附加”),您应该确保用户不会因执行上述建议而感到困惑。

    我的组件还没有完成,我会尽量记住自己稍后分享代码。如果这个问题超过一个月左右,请发表评论。

    编辑:结果

    <div fxLayout="row">
      <div *ngIf="!dateOnly" [formGroup]="timeFormGroup">
        <mat-form-field>
          <input matInput [ngxTimepicker]="endTime" [format]="24"  placeholder="{{placeholderTime}}" formControlName="endTime" />
        </mat-form-field>
        <ngx-material-timepicker #endTime (timeSet)="timeChange($event)" [minutesGap]="10"></ngx-material-timepicker>
      </div>
      <div>
        <mat-form-field>
          <input id="pickerId" matInput [matDatepicker]="datepicker" placeholder="{{placeholderDate}}" [formControl]="dateForm"
                 [min]="config.minDate" [max]="config.maxDate" (dateChange)="dateChange($event)">
          <mat-datepicker-toggle matSuffix [for]="datepicker"></mat-datepicker-toggle>
          <mat-datepicker #datepicker [disabled]="disabled" [touchUi]="config.touchUi" startView="{{config.startView}}"></mat-datepicker>
        </mat-form-field>
      </div>
    </div>
    
    import { Component, OnInit, Input, EventEmitter, Output } from '@angular/core';
    import { FormControl, FormGroup } from '@angular/forms';
    import { DateAdapter, MatDatepickerInputEvent } from '@angular/material';
    
    import * as moment_ from 'moment';
    
    const moment = moment_;
    
    import { MAT_MOMENT_DATE_ADAPTER_OPTIONS } from '@angular/material-moment-adapter';
    
    class DateConfig {
      startView: 'month' | 'year' | 'multi-year';
      touchUi: boolean;
      minDate: moment_.Moment;
      maxDate: moment_.Moment;
    }
    
    @Component({
      selector: 'cb-datetimepicker',
      templateUrl: './cb-datetimepicker.component.html',
      styleUrls: ['./cb-datetimepicker.component.scss'],
    })
    export class DatetimepickerComponent implements OnInit {
    
      @Input() disabled: boolean;
      @Input() placeholderDate: string;
      @Input() placeholderTime: string;
      @Input() model: Date;
      @Input() purpose: string;
      @Input() dateOnly: boolean;
    
      @Output() dateUpdate = new EventEmitter<Date>();
    
      public pickerId: string = "_" + Math.random().toString(36).substr(2, 9);
    
      public dateForm: FormControl;
      public timeFormGroup: FormGroup;
      public endTime: FormControl;
    
      public momentDate: moment_.Moment;
      public config: DateConfig;
    
      //myGroup: FormGroup;
    
    
      constructor(private adapter : DateAdapter<any>) { }
    
      ngOnInit() {
    
        this.adapter.setLocale("nl-NL");//todo: configurable
        this.config = new DateConfig();
        if (this.purpose === "birthday") {
          this.config.startView = 'multi-year';
          this.config.maxDate = moment().add('year', -15);
          this.config.minDate = moment().add('year', -90);
          this.dateOnly = true;
        } //add more configurations
        else {
          this.config.startView = 'month';
          this.config.maxDate = moment().add('year', 100);
          this.config.minDate = moment().add('year', -100);
        }
    
    
        if (window.screen.width < 767) {
          this.config.touchUi = true;
        }
    
    
    
        if (this.model) {
          var mom = moment(this.model);
          if (mom.isBefore(moment('1900-01-01'))) {
            this.momentDate = moment();
          } else {
            this.momentDate = mom;
          }
        } else {
          this.momentDate = moment();
        }
    
        this.dateForm = new FormControl(this.momentDate);
        if (this.disabled) {
          this.dateForm.disable();
        }
        this.endTime = new FormControl(this.momentDate.format("HH:mm"));
    
        this.timeFormGroup = new FormGroup({
          endTime: this.endTime
        });
    
    
      }
    
    
      public dateChange(date: MatDatepickerInputEvent<any>) {
    
        if (moment.isMoment(date.value)) {
          this.momentDate = moment(date.value);
          if (this.dateOnly) {
            this.momentDate = this.momentDate.utc(true);
          } 
          var newDate = this.momentDate.toDate();
          this.model = newDate;
          this.dateUpdate.emit(newDate);
        }
    
        console.log("datechange",date);
      }
    
      public timeChange(time: string) {
    
        var splitted = time.split(':');
        var hour = splitted[0];
        var minute = splitted[1];
    
        console.log("time change", time);
       this.momentDate = this.momentDate.set('hour', parseInt(hour));
        this.momentDate = this.momentDate.set('minute', parseInt(minute));
    
        var newDate = this.momentDate.toDate();
        this.model = newDate;
        this.dateUpdate.emit(newDate);
      }
    }
    

    一个重要来源:https://github.com/Agranom/ngx-material-timepicker/issues/126

    我认为它仍然值得一些调整,因为我认为当我有更多时间创建它时它可以更好地工作。最重要的是,我也尝试解决 UTC 问题,因此所有日期都应以当地时间显示,但应以 UTC 格式发送到服务器(或至少保存时添加了正确的时区)。

    【讨论】:

    • 一个月左右...好奇你的解决方案:-)。
    • @TimHarker 对结果不是 100% 满意,需要一些调整,但我认为这是一个好的开始,我没有解决我提到的要求,它仍在待办事项列表中。所以请随意完成我的要求并更新答案:)
    • Agranom 库已过时(支持最大 Angular 8)
    • 感谢 Pedro 的提醒,看起来他现在比 2 年前不那么活跃了,使用开源库总是很难让有人继续致力于该项目。
    【解决方案4】:

    很遗憾,您关于选择时间是否有官方 Material 支持的问题的答案是“否”,但目前在 Material2 官方 GitHub repo 上是一个未解决的问题:https://github.com/angular/material2/issues/5648

    希望这种情况很快就会改变,与此同时,你将不得不与你已经发现的第 3 方战斗。该 GitHub 问题中有几个人提供了他们自制的解决方法,您可以尝试。

    【讨论】:

    • @KevinCurnow:你能分享一下解决方案吗?我需要一个日期范围选择器和时间选择器。我的另一个限制是我需要让它在 Angular4 中工作。我知道有一个可用于 6
    【解决方案5】:

    自 4 年前以来,目前有一个针对 Angular 团队的官方公开问题,要求支持时间和日期时间选择器:https://github.com/angular/components/issues/5648

    正如您在这篇文章中看到的那样,那里有很多库,问题是它们中的大多数已被弃用(较旧的 Angular 版本)。

    所以,我实际上使用的是来自@matheo 的这个,它是我发现的最新和维护的:

    https://www.npmjs.com/package/@coachcare 最近移至https://www.npmjs.com/package/@matheo/datepicker


    演示:http://matheo.co/demos/datepicker



    注意:如果它不适用于 Angular 版本 >= 12,请检查是否使用了新的 Angular 约定主题,例如:

    @use "~@matheo/datepicker/theming" as datepicker;
    // ...
    @include datepicker.mat-datepicker-theme($main_theme);
    

    【讨论】:

    • 这个是否支持为日期选择器设置时区? @佩德罗
    • 嗨@AleksandarT,理论上是的,但是我在实现它时遇到了很多麻烦......
    • @matheo/datepicker 包包含 .mjs 文件,Node.js 以我的应用程序配置不支持的方式将其视为 ECMAScript 模块。我试着搞乱 webpack 模块配置的东西,但现在已经放弃了。导入组件会导致数百个错误如:Microsoft.AspNetCore.SpaServices: Error: ERROR in ../node_modules/@matheo/datepicker/core/datetime/index.d.ts:8:21 - error TS2694: Namespace '"C:/projects/app/node_modules/@angular/core/core"' has no exported member '╔╡╔╡FactoryDeclaration'.
    【解决方案6】:

    【讨论】:

    • 知道如何解决这个day-time-picker 的问题吗? ERROR TypeError: Cannot read property 'locale' of undefined at DayTimeCalendarService.push../node_modules/ng2-date-picker/fesm5/ng2-date-picker.js.DayTimeCalendarService.getConfig (ng2-date-picker.js:999) at DayTimeCalendarComponent.push../node_modules/ng2-date-picker/fesm5/ng2-date-picker.js.DayTimeCalendarComponent.init (ng2-date-picker.js:1691) at DayTimeCalendarComponent.push../node_modules/ng2-date-picker/fesm5/ng2-date-picker.js.DayTimeCalendarComponent.ngOnInit (ng2-date-picker.js:1687)
    • 我也安装了依赖项(moment & tslib)
    • 我猜你需要时刻语言环境
    • 我确实将moment-with-locales.min.js 文件添加到我的资产文件夹中
    • 我建议你在 github repo 中打开一个 issue,stackblitz 会有所帮助
    【解决方案7】:

    实现日期和时间控制的最佳方式是使用输入类型“datetime-local”。 请参考https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/datetime-local

    示例代码是

    <mat-grid-list [cols]="5" gutterSize="20px" rowHeight="70px">
                    <form *ngIf="dateForm && dateForm !== null" [formGroup]="dateForm">
                        <mat-grid-tile>
                            <mat-form-field appearance="outline" floatLabel="auto">
                                <mat-label>From Date</mat-label>
                                <input type="datetime-local" matInput name="fromTime" formControlName="fromDate">
                            </mat-form-field>
                        </mat-grid-tile>
                        <mat-grid-tile>
                            <mat-form-field appearance="outline" floatLabel="auto">
                                <mat-label>To Date</mat-label>
                                <input type="datetime-local" matInput name="toTime" formControlName="toDate">
                            </mat-form-field>
                        </mat-grid-tile>
                    </form>
    </mat-grid-list>
    

    【讨论】:

    • 这行得通,但是 firefox 和 chrome 赋予它不同的功能,在 chrome 中你会得到一个小的模拟时钟图标,点击时会产生一个下拉帮助程序,但这些在 firefox 中不存在。
    猜你喜欢
    • 1970-01-01
    • 2018-09-13
    • 1970-01-01
    • 2019-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多