Angular-Material DateTime Picker Component?

前端 未结 6 1991
不知归路
不知归路 2021-02-03 17:13

I imported a date picker in a project and was wondering if there was any official recent component from angular and material to include time in the calendar as well.
I\'ve s

6条回答
  •  伪装坚强ぢ
    2021-02-03 18:03

    For as long as there is no official date and time picker from angular itself, I would advise to make a combination of the default angular date picker and this Angular Material Timepicker. I've chosen that one because all the other ones I found at this time lack support for issues, are outdated or are not functioning well in the most recent angular versions. This guy seems to be very responsive.

    I've wrapped them both in one component so that it looks like it is one unit. You just have to make sure to do a few things:

    When no input has been given yet, I would advise:

    • On-click of the component, the datepicker should always be triggered first.
    • After the datepicker closes, have the timepicker automatically popup.
    • Use touchUi = true on the datepicker, so that both the datepicker and the timepicker come as a dialog after each other.
    • Make sure the datepicker also shows up when clicking on the form (instead of only on the icon which is the default).
    • Use this solution to use the timepicker also in a material form, when placing them behind each other, it looks like it is one form.

    After a value has been given, it is clear that one part contains the time and the other part contains the date. At that moment it is clear that the user has to click on the time to change the time, and on the date to change the date. But before that, so when both fields are empty (and 'attached' to each other as one field) you should make sure the user cannot be confused by doing above recommendations.

    My component is not complete yet, I will try to remember myself to share the code later. Shoot a comment if this question is more then a month old or so.

    Edit: Result

    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();
    
      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) { }
    
      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) {
    
        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);
      }
    }
    

    One important source: https://github.com/Agranom/ngx-material-timepicker/issues/126

    I think it still deserves some tweaks, as I think it can work a bit better when I would have more time creating this. Most importantly I tried to solve the UTC issue as well, so all dates should be shown in local time but should be sent to the server in UTC format (or at least saved with the correct timezone added to it).

提交回复
热议问题