Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bind an input with type datetime-local to a Date property in Angular 2

It is possible to bind a component property of Date type to a HTML5 input with type set to datetime-local?

In my component I have a poperty:

public filterDateFrom: Date; 

and in my template I have an input defined as:

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

but binding doesn't work.

like image 664
Dominik Palo Avatar asked Dec 31 '15 12:12

Dominik Palo


People also ask

How to bind date and time in angular?

You can bind to a date using the following format: yyyy-MM-ddTHH:mm , which you can also get from date. toISOString(). slice(0,16) (the slice removes the time portion after the minutes).

How do I change the input date format?

To set and get the input type date in dd-mm-yyyy format we will use <input> type attribute. The <input> type attribute is used to define a date picker or control field. In this attribute, you can set the range from which day-month-year to which day-month-year date can be selected from.


2 Answers

Demo Plnkr

You can bind to a date using the following format: yyyy-MM-ddTHH:mm, which you can also get from date.toISOString().slice(0,16) (the slice removes the time portion after the minutes).

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

Keep in mind that date.toISOString() will return a date offset from local time. You can also construct the date string yourself:

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

If you want to be able to bind the select to a Date model, you can use this to build a custom date component:

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

Users of your component would bind to a Date model with two-way model binding:

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

Or if you want to avoid custom tags, rewrite the component as a directive:

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

Demo Plnkr with Directive

like image 149
pixelbits Avatar answered Oct 08 '22 13:10

pixelbits


Now that its Spring 2017, DatePipe is shipped OOTB. You can achieve (one-way) binding by specifying format parameters to the pipe. For example:

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

Slight caveat is that you can not use two-way binding with this technique, you have to use one way binding with the data pipe, then manage the DOM to model change events to handle client changes to the control (unless I'm missing something!), but it seems a lot cleaner this way.


Update

Looks like I was indeed missing something!

Adding ngModelChange to the above should provide the DOM --> model side of the two-way binding process:

<input type="datetime-local"         [ngModel]="filterDateFrom | date:'yyyy-MM-ddTHH:mm'"        (ngModelChange)="filterDateFrom = $event" /> 
like image 39
ne1410s Avatar answered Oct 08 '22 13:10

ne1410s