web-dev-qa-db-ja.com

タイプdatetime-localの入力をAngular 2のDateプロパティにバインドします

タイプをdatetime-local?に設定して、DateタイプのコンポーネントプロパティをHTML5入力にバインドできます。

私のコンポーネントにはポパーティがあります:

public filterDateFrom: Date;

私のテンプレートには、次のように定義された入力があります。

<input type="datetime-local" [(ngModel)]="filterDateFrom" />

しかし、バインディングは機能しません。

17
Dominik Palo

デモPlnkr

次の形式を使用して日付にバインドできます:_yyyy-MM-ddTHH:mm_。これはdate.toISOString().slice(0,16)からも取得できます(スライスは分後に時間部分を削除します)。

_@Component({
    selector: 'app',
    template: `<input type="datetime-local" [value]="date" 
          (change)="date=$event.target.value" /> {{date}}` 
})
export class AppComponent {
    date: string;
    constructor() {
        this.date = new Date().toISOString().slice(0, 16);
    }
}
_

date.toISOString()は現地時間からの日付オフセットを返すことに注意してください。日付文字列を自分で作成することもできます。

_private toDateString(date: Date): string {
    return (date.getFullYear().toString() + '-' 
       + ("0" + (date.getMonth() + 1)).slice(-2) + '-' 
       + ("0" + (date.getDate())).slice(-2))
       + 'T' + date.toTimeString().slice(0,5);
}
_

SelectをDateモデルにバインドできるようにしたい場合、これを使用してカスタム日付コンポーネントを作成できます。

_@Component({
    selector: 'my-date',
    events: ['dateChange'],
    template: `<input type="datetime-local" [value] = "_date" 
             (change) = "onDateChange($event.target.value)" />`
})
export class MyDate{
    private _date: string;
    @Input() set date(d: Date) {
        this._date = this.toDateString(d);
    }
    @Output() dateChange: EventEmitter<Date>;
    constructor() {
        this.date = new Date();
        this.dateChange = new EventEmitter();       
    }

    private toDateString(date: Date): string {
        return (date.getFullYear().toString() + '-' 
           + ("0" + (date.getMonth() + 1)).slice(-2) + '-' 
           + ("0" + (date.getDate())).slice(-2))
           + 'T' + date.toTimeString().slice(0,5);
    }

    private parseDateString(date:string): Date {
       date = date.replace('T','-');
       var parts = date.split('-');
       var timeParts = parts[3].split(':');

      // new Date(year, month [, day [, hours[, minutes[, seconds[, ms]]]]])
      return new Date(parts[0], parts[1]-1, parts[2], timeParts[0], timeParts[1]);     // Note: months are 0-based

    }

    private onDateChange(value: string): void {
        if (value != this._date) {
            var parsedDate = this.parseDateString(value);

            // check if date is valid first
            if (parsedDate.getTime() != NaN) {
               this._date = value;
               this.dateChange.emit(parsedDate);
            }
        }
    }
}
_

コンポーネントのユーザーは、双方向モデルバインディングでDateモデルにバインドします。

_@Component({
    selector: 'my-app',
    directives: [MyDate],
    template: '<my-date [(date)]="date"></my-date>  {{date}}' 
})
export class AppComponent {
    @Input() date: Date;
    constructor() {
        this.date = new Date();
    }
}
_

または、カスタムタグを回避する場合は、コンポーネントをディレクティブとして書き換えます。

_<input type="datetime-local" [(date)]="date" />
_

ディレクティブ付きデモPlnkr

20
pixelbits

2017年春、DatePipeはOOTBで出荷されました。パイプに形式パラメーターを指定することにより、(一方向の)バインディングを実現できます。例えば:

<input type="datetime-local" [ngModel]="filterDateFrom | date:'yyyy-MM-ddTHH:mm'" />

若干の注意点は、DOMを管理する必要があることです->コントロールのクライアントの変更を処理するために物事のモデル側(何かが足りない場合を除きます!).


更新

私は本当に何かを逃していたようです!

ngModelChangeを上記に追加すると、双方向バインディングプロセスのDOM->モデル側が提供されます。

<input type="datetime-local" 
       [ngModel]="filterDateFrom | date:'yyyy-MM-ddTHH:mm'
       (ngModelChange)="filterDateFrom = $event" />
6
ne1410s

私もこの問題を調査していましたが、この例の道を進み始めました。ただし、[date、datetime、datetime-local]型の入力で[(ngModel)]を使用できます。重要なのは、コントロールが期待している期待される形式と一致させることです。この場合、 この形式 が期待されます。また、コントロールにバインドする型は文字列である必要があります。例 plunker を提供しました。これは、[(ngModel)]の使用方法を示しています。

import { Component } from 'angular2/core';

@Component({
  selector: 'my-app',
  template: `
      <form>
        <input type="datetime-local" [(ngModel)]="dateTimeLocal"><br />
        {{dateTimeLocal}}
      </form>
    `
})
export class AppComponent {
  private _dateTimeLocal: Date;

  constructor() {
    this._dateTimeLocal = new Date();
  }

  private parseDateToStringWithFormat(date: Date): string {
    let result: string;
    let dd = date.getDate().toString();
    let mm = (date.getMonth() + 1).toString();
    let hh = date.getHours().toString();
    let min = date.getMinutes().toString();
    dd = dd.length === 2 ? dd : "0" + dd;
    mm = mm.length === 2 ? mm : "0" + mm;
    hh = hh.length === 2 ? hh : "0" + hh;
    min = min.length === 2 ? min : "0" + min;
    result = [date.getFullYear(), '-', mm, '-', dd, 'T', hh, ':', min].join('');

    return result;
  }

  public set dateTimeLocal(v: string) {
    let actualParsedDate = v ? new Date(v) : new Date();
    let normalizedParsedDate = new Date(actualParsedDate.getTime() + (actualParsedDate.getTimezoneOffset() * 60000));
    this._dateTimeLocal = normalizedParsedDate;
  }


  public get dateTimeLocal(): string {
    return this.parseDateToStringWithFormat(this._dateTimeLocal);
  }
}
4
Dan Simon

@ ne1410sの答えに触発されて、日付の種類を失うことなく、非常に似たようなことをやめました。

パイプを使用してngModelを宣言し、dateChangedの新しいDateの変換を返すためにメソッドtsを呼び出します。

htmlコード:

<input type="datetime-local" [ngModel]="filterDateFrom | date:'yyyy-MM-ddTHH:mm'" (ngModelChange)="filterDateFrom = dateChanged($event)"/>

tsコード:

 dateChanged(eventDate: string): Date | null {
   return !!eventDate ? new Date(eventDate) : null;
 }
0
Daniel Piñeiro