日期选择器的弹出窗口显示错误的年份

Popup from datepicker showing wrong year

angular 中日期选择器的弹出窗口在打开时显示错误的年份。然而,从 2011 年 12 月之后的那一年开始改为 2021 年。

我正在使用 Angular 12.2.0 和 Bootstrap 4.3.1。我无法弄清楚如何更改它。可能是兼容性问题?对不起我只能link图片因为“声望点数”:P

Datepicker

日期-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>

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

}

不幸的是,我不太确定为什么默认为 2011 年。

但是,在提供更好的答案之前,根据 ngb-datepicker 文档(https://ng-bootstrap.github.io/#/components/datepicker/overview,标题为内容模板的部分),您可以提供

[startDate] = "{month: {month}, year: {year}"

到 html 组件标签。也许您可以同时使用它来手动确保年份是当前年份。

ng-bootstrap 已过时。更新到 10.0.0 是我的解决方案。