Search code examples
angularangular-materialdatepicker

Angular Datepicker with format MM.yyyy wants to select day


I want to use a datepicker that only accepts month and year. According to Angular Materials I built a function which should close the datepicker after the month has been selected - so that no day can be selected. The first time the datepicker is called (regardless of whether a value has already been saved here) the day is still required. However, when you call it up again it doesn't.

<mat-form-field fxFlex [subscriptSizing]="subscriptSizing">
    <mat-label>{{label}}</mat-label>
    <input matInput [matDatepicker]="picker" [formControl]="control" autocomplete="off">
    <mat-datepicker-toggle matIconSuffix [for]="picker"></mat-datepicker-toggle>
    <mat-datepicker #picker 
    startView="multi-year" 
    (yearSelected)="chosenYearHandler($event)"
    (monthSelected)="chosenMonthHandler($event, picker)"
    panelClass="example-month-picker"></mat-datepicker>
  </mat-form-field>

ts file:

  chosenYearHandler(normalizedYear: Moment) {
    const ctrlValue = this.control.value;
    ctrlValue.year(normalizedYear.year());
    this.control.setValue(ctrlValue);
  }

  chosenMonthHandler(normalizedMonth: Moment, datepicker: MatDatepicker<Moment>) {
    const ctrlValue = this.control.value;
    ctrlValue.month(normalizedMonth.month());
    this.control.setValue(ctrlValue);
    datepicker.close();
  }

The date is injected by a control.

I'm a beginner in angular, any help is very much appreciated!


Solution

  • The reason why the first time requires you to select a day is that ctrlValue is null, and it breaks the code when calling ctrlValue.year(/* value */) and ctrlValue.month(/* value */).

    Instead, modify your code as below by setting the control value when chosenMonthHandler is triggered.

    chosenYearHandler(normalizedYear: Moment) {}
    
    chosenMonthHandler(
      normalizedMonth: Moment,
      datepicker: MatDatepicker<Moment>
    ) {
      this.control.setValue(normalizedMonth);
      datepicker.close();
    }
    

    Demo @ StackBlitz