The popup from the datepicker in angular is showing the wrong year when opened. However the year after December 2011 is changing to 2021 as it should be from the beginning.
I am using Angular 12.2.0 with Bootstrap 4.3.1. I cant figure out how to change this.. Maybe compatibility issues? Sorry I can only link the image because of "reputation points" :P
date-picker.component.html
<div class="input-group input-group-sm">
<input class="form-control" name="dp" [(ngModel)]="selectedDate" ngbDatepicker #d="ngbDatepicker" (change)="onDateChange($event.target.value)" (dateSelect)="onDateSelect($event)" [disabled]="isDisabled ? 'disabled' : null">
<div class="input-group-append" *ngIf="!isDisabled">
<button class="btn btn-input calendar fa fa-calendar" (click)="d.toggle()" type="button"></button>
</div>
</div>
date-picker.component.ts
import { Component, OnInit, ViewEncapsulation, forwardRef, Injectable, Output, EventEmitter } from '@angular/core';
import { NgbDateParser } from '../../ngb-date-parser';
import { NgbDateParserFormatter, NgbDatepickerI18n, NgbDateStruct } from '@ng-bootstrap/ng-bootstrap';
import { ControlValueAccessor, NG_VALUE_ACCESSOR, } from '@angular/forms';
const I18N_VALUES = {
'it-IT': {
weekdays: ['Lu', 'Ma', 'Me', 'Go', 'Ve', 'Sa', 'Do'],
months: ['Gen', 'Feb', 'Mar', 'Apr', 'Mag', 'Giu', 'Lug', 'Ago', 'Set', 'Ott', 'Nov', 'Dic'],
},
'de-DE': {
weekdays: ['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So'],
months: ['Jan', 'Feb', 'Mar', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'],
},
'en-US': {
weekdays: ['Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su'],
months: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
},
'en-UK': {
weekdays: ['Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su'],
months: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
}
};
@Injectable()
export class I18n {
language = localStorage.getItem('locale');
}
// Define custom service providing the months and weekdays translations
@Injectable()
export class CustomDatepickerI18n extends NgbDatepickerI18n {
constructor(private i18n: I18n) {
super();
}
getWeekdayShortName(weekday: number): string {
return I18N_VALUES[this.i18n.language].weekdays[weekday - 1];
}
getMonthShortName(month: number): string {
return I18N_VALUES[this.i18n.language].months[month - 1];
}
getMonthFullName(month: number): string {
return this.getMonthShortName(month);
}
getDayAriaLabel(date: NgbDateStruct): string {
return `${date.day}-${date.month}-${date.year}`;
}
}
export const DATEPICKER_VALUE_ACCESSOR = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => DatePickerComponent),
multi: true
};
@Component({
selector: 'app-date-picker',
templateUrl: './date-picker.component.html',
styleUrls: ['./date-picker.component.scss'],
providers: [DATEPICKER_VALUE_ACCESSOR, {provide: NgbDateParserFormatter, useClass: NgbDateParser},
I18n, {provide: NgbDatepickerI18n, useClass: CustomDatepickerI18n}]
})
export class DatePickerComponent implements ControlValueAccessor {
selectedDate: any;
isDisabled = false;
@Output() dateChange = new EventEmitter<any>();
constructor() {}
// Function to call when the date changes.
onChange = (date?: Date) => {
};
// Function to call when the date picker is touched
onTouched = () => {};
writeValue(value: Date) {
if (!value) {
this.selectedDate = undefined;
return;
}
value = new Date(value);
this.selectedDate = {
year: value.getFullYear(),
month: value.getMonth()+1,
day: value.getDate()
}
}
registerOnChange(fn: (date: Date) => void): void {
this.onChange = fn;
}
// Allows Angular to register a function to call when the input has been touched.
// Save the function as a property to call later here.
registerOnTouched(fn: () => void): void {
this.onTouched = fn;
}
// Allows Angular to disable the input.
setDisabledState(isDisabled: boolean): void {
this.isDisabled = isDisabled;
}
// Write change back to parent
onDateChange(value: string) {
const dateString = value.split('.');
if(dateString.length == 3) {
const date: Date = new Date(+dateString[2], +dateString[1]-1, +dateString[0]);
this.onChange(date);
}
if (value == null || value == '') {
this.onChange(null);
}
}
// Write change back to parent
onDateSelect(value: any) {
this.onChange(new Date(value.year, value.month - 1, value.day));
this.dateChange.emit(value);
}
}
ng-bootstrap was outdated. An update to 10.0.0 was the solution for me.