Introduction
The HTML input element of type datetime-local, keeps the values as ISO time string, while the displayed text is based on language of the web browser (specifically chrome) and not on the default windows format.
The issue we want to solve is to independently of the browser or the OS, display the value according to our own rules, e.g. DD-MM-YYYY all the time.
Solution
The proposed solution is for Angular however, it can be easily transformed into any other framework:
The template of the wrapper component for the datetime-local should be like this:
<input type="datetime-local" [value] = "_date" (change) = "onDateChange($event)"
[attr.data-date]="dataDate" />
We enable binding of DateTime object as well as format (using the moment library) the date according to some format we choose (stored in variable - 'format').
dataDate = "";
@Input() set date(d: Date | null) {
this._date = moment(d!).format("yyyy-MM-DDThh:mm");
let format = moment.localeData(this.translate.getDefaultLang()).longDateFormat('L');
this.dataDate = moment(this._date, "YYYY-MM-DD").format(format);
}
@Output() dateChange: EventEmitter<Date>;
onDateChange(event: any): void {
let value = event.target.value
if (value != this._date) {
const parsedDate = moment(value, "yyyy-MM-DDThh:mm").toDate();
// check if date is valid first
if (parsedDate.getTime() != NaN) {
this._date = value;
this.dateChange.emit(parsedDate);
}
}
let format = moment.localeData(this.translate.getDefaultLang()).longDateFormat('L');
this.dataDate = moment(value, "YYYY-MM-DD").format(format);
}
We save the (correctly) formatted date in the dateData property.
Then, using CSS rules, we hide the original input and show instead the contents of the property.
input {
position: relative;
color: white;
}
input:before {
position: absolute;
top: 3px; left: 3px;
content: attr(data-date);
display: inline-block;
color: black;
}
input::-webkit-datetime-edit, input::-webkit-inner-spin-button, input::-webkit-clear-button {
display: none;
}
input::-webkit-calendar-picker-indicator {
position: absolute;
top: 3px;
right: 0px;
color: black;
opacity: 1;
}