Saltar al contenido

Vincular una entrada con el tipo datetime-local a una propiedad Date en Angular 2

Solución:

Demo Plnkr

Puede enlazar a una fecha usando el siguiente formato: yyyy-MM-ddTHH:mm, que también puede obtener de date.toISOString().slice(0,16) (la rebanada elimina la porción de tiempo después de los minutos).

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

Manten eso en mente date.toISOString() devolverá una diferencia de fecha con respecto a la hora local. También puede construir la cadena de fecha usted mismo:

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

Si desea poder enlazar la selección a un Date modelo, puede usar esto para construir un componente de fecha personalizado:

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

Los usuarios de su componente se vincularían a un Date modelo con encuadernación de modelo bidireccional:

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

O si desea evitar las etiquetas personalizadas, vuelva a escribir el componente como una directiva:

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

Demo Plnkr con Directiva

Ahora que es primavera de 2017, DatePipe se envía OOTB. Puede lograr un enlace (unidireccional) especificando parámetros de formato en la tubería. Por ejemplo:

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

Una pequeña advertencia es que no puede usar un enlace bidireccional con esta técnica, debe usar un enlace unidireccional con la tubería de datos, luego administrar el DOM para modelar los eventos de cambio para manejar los cambios del cliente en el control (a menos que me falte algo !), pero parece mucho más limpio de esta manera.


Actualizar

¡Parece que de hecho me estaba perdiendo algo!

Añadiendo ngModelChange a lo anterior debe proporcionar el DOM -> lado del modelo del proceso de enlace bidireccional:

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

También estaba investigando este problema y comencé a seguir este camino de ejemplos. Sin embargo, puede utilizar [(ngModel)] en una entrada del tipo [date,datetime,datetime-local]. La clave es hacer coincidir el formato esperado que espera el control. En este caso espera este formato. Lo que también significa que el tipo que se une al control debe ser una cadena. He proporcionado un plunker de ejemplo, que demuestra cómo usar [(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);
  }
}

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *