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.
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).
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.
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
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.
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" />
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With