web-dev-qa-db-ja.com

角材日付時間ピッカーコンポーネント?

プロジェクトに date picker をインポートしましたが、angularからの公式の最近のコンポーネントやカレンダーに時間を含めるための素材があるかどうか疑問に思いました。
マテリアルドキュメントで多くのタイムピッカーを見てきましたし、多くのサードパーティのものを調査しましたが、非常に複雑に見えます。

17
Kevin Curnow

残念ながら、時刻を選択するための公式のマテリアルサポートがあるかどうかの質問への答えは「いいえ」ですが、現時点では公式のMaterial2 GitHubリポジトリの未解決の問題です。 https://github.com/angular/ material2/issues/5648

すぐにこの変更が行われることを願っていますが、その間に、既に発見したサードパーティのものと戦わなければなりません。そのGitHubの問題には、自分で作成できる回避策を提供できる人がいます。

14
JeremyW

タイプdatetime-localmatInputを使用する場合、日付ピッカーを使用できます。

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

プレースホルダーの各部分をクリックして、日、月、年、時間、分、およびAMまたはPMを設定できます。

8
Maurice

angular自体からの公式の日付およびタイムピッカーがない限り、-の組み合わせを作成することをお勧めします デフォルトangular日付ピッカー およびこれ Angular Material Timepicker 。私が現時点で見つけた他のすべてのものが問題のサポートを欠いている、最新のものである、または最新のangularバージョンでうまく機能していないので、私はそれを選んだ。この男は非常に敏感です。

両方を1つのコンポーネントにラップして、1つのユニットに見えるようにしました。いくつかのことを確認する必要があります。

入力がまだ与えられていない場合、私はお勧めします:

  • コンポーネントをクリックすると、日付ピッカーが常に最初にトリガーされるはずです。
  • 日付ピッカーが閉じた後、タイムピッカーを自動的にポップアップさせます。
  • DatepickerでtouchUi = trueを使用して、datepickerとtimepickerの両方がダイアログとして表示されるようにします。
  • デフォルトのアイコンのみではなく、フォームをクリックしたときに日付ピッカーも表示されることを確認します。
  • このソリューション を使用して、タイムピッカーをマテリアルフォームでも使用します。それらを互いの後ろに配置すると、1つのフォームのように見えます。

値が与えられた後、1つの部分に時刻が含まれ、他の部分に日付が含まれることは明らかです。その時点で、ユーザーが時刻をクリックして時刻を変更し、日付をクリックして日付を変更する必要があることは明らかです。ただし、その前に、両方のフィールドが空の場合(および1つのフィールドとして互いに「接続」されている場合)、上記の推奨事項を実行してユーザーが混乱しないようにする必要があります。

私のコンポーネントはまだ完成していません。後でコードを共有するために自分自身を思い出そうとします。この質問が1か月以上経過している場合は、コメントを投稿してください。

編集:結果

enter image description here

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

1つの重要なソース: https://github.com/Agranom/ngx-material-timepicker/issues/126

私はこれを作成する時間がもっとあると少し良くなると思うので、まだいくつかの調整に値すると思います。最も重要なことは、UTCの問題も解決しようとしたため、すべての日付を現地時間で表示する必要がありますが、UTC形式でサーバーに送信する必要があります(または少なくとも正しいタイムゾーンが追加されて保存されます)。

2
CularBytes

チェックアウトすることをお勧めします https://vlio20.github.io/angular-datepicker/

enter image description here

1
vlio20