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

Posted

技术标签:

【中文标题】日期选择器的弹出窗口显示错误的年份【英文标题】:Popup from datepicker showing wrong year 【发布时间】:2021-11-17 18:19:27 【问题描述】:

日期选择器的弹出窗口在打开时显示错误的年份。然而,2011 年 12 月之后的一年正从一开始就变成了 2021 年。

我正在使用带有 Bootstrap 4.3.1 的 Angular 12.2.0。我不知道如何改变这个..也许是兼容性问题?对不起,我只能链接图像,因为“声誉点”:P

Datepicker

日期选择器.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>

日期选择器.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);
  


【问题讨论】:

【参考方案1】:

不幸的是,我不太清楚为什么它会默认为 2011 年。

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

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

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

【讨论】:

我注意到在使用您的解决方法时,年份总是比我在 [startDate] 中写的少 10 年。例如,如果我使用 2000 年,则弹出窗口显示 1990。这就是它显示 2011(2021 - 10)的原因。奇怪的行为。 很奇怪,是的,我想现在的解决方法是获取当前年份并添加 10 大声笑,不理想。我想知道您是否要在一个空项目中重建您的日期选择器并查看问题是否仍然存在。然后,慢慢地对其进行更改,当你添加你所拥有的每一个东西时,测试一下,看看日期是否/在哪里可以追溯到十年前。【参考方案2】:

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

【讨论】:

以上是关于日期选择器的弹出窗口显示错误的年份的主要内容,如果未能解决你的问题,请参考以下文章

android有月份选择器吗?或者怎么让日期选择器的日期不显示,只显示年份和月份

在移动设备上禁用 Bootstrap 日期选择器的键盘弹出窗口(Rails 4,Jquery)

弹出窗口中的 Xamarin.Forms 日期选择器

引导日期选择器弹出窗口未显示突出显示的当前日期

如何更改html5中自动日期选择器的显示格式

如何设置 jQuery 日期选择器的年份范围:1900 到当前年份,或 1900 到 9999