You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Angular Material实现仅选年月的MM/YYYY格式日期范围选择器

Angular Material 实现MM/YYYY格式年月范围选择器

基于你已完成的单年月选择器逻辑,改造为范围选择器只需替换日期范围组件、调整表单结构和选中回调即可,完整实现如下:

1. TS 逻辑调整

将单个表单控件替换为表单组管理起止日期,新增选择阶段标记区分当前选中的是开始月还是结束月,补充日期大小校验避免结束日期早于开始日期:

import {Component} from '@angular/core';
import {FormGroup, FormControl} from '@angular/forms';
import {MomentDateAdapter, MAT_MOMENT_DATE_ADAPTER_OPTIONS} from '@angular/material-moment-adapter';
import {DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE} from '@angular/material/core';
import {MatDateRangePicker} from '@angular/material/datepicker';
import * as _moment from 'moment';
import {default as _rollupMoment, Moment} from 'moment';

const moment = _rollupMoment || _moment;

// 自定义年月显示格式,与单日期选择器配置保持一致
export const MY_FORMATS = {
  parse: {
    dateInput: 'MM/YYYY',
  },
  display: {
    dateInput: 'MM/YYYY',
    monthYearLabel: 'MMM YYYY',
    dateA11yLabel: 'LL',
    monthYearA11yLabel: 'MMMM YYYY',
  },
};

@Component({
  selector: 'month-range-picker-example',
  templateUrl: 'month-range-picker-example.html',
  styleUrls: ['month-range-picker-example.css'],
  providers: [
    {
      provide: DateAdapter,
      useClass: MomentDateAdapter,
      deps: [MAT_DATE_LOCALE, MAT_MOMENT_DATE_ADAPTER_OPTIONS],
    },
    {provide: MAT_DATE_FORMATS, useValue: MY_FORMATS},
  ],
})
export class MonthRangePickerExample {
  // 表单组管理起止日期
  dateRange = new FormGroup({
    start: new FormControl(moment()),
    end: new FormControl(moment().add(1, 'month'))
  });
  // 标记当前选择阶段:选择开始月/选择结束月
  private currentSelectPhase: 'start' | 'end' = 'start';

  setMonthAndYear(selectedMonth: Moment, datepicker: MatDateRangePicker<Moment>) {
    const targetDate = moment(selectedMonth);
    if (this.currentSelectPhase === 'start') {
      // 赋值开始月,自动切换到结束月选择阶段
      this.dateRange.patchValue({start: targetDate});
      this.currentSelectPhase = 'end';
    } else {
      // 校验结束月与开始月的大小关系
      if (targetDate.isBefore(this.dateRange.value.start)) {
        // 结束月早于开始月时自动交换两个值
        this.dateRange.patchValue({
          start: targetDate,
          end: this.dateRange.value.start
        });
      } else {
        this.dateRange.patchValue({end: targetDate});
      }
      // 选完结束月后重置阶段,关闭选择面板
      this.currentSelectPhase = 'start';
      datepicker.close();
    }
  }
}

2. HTML 模板调整

将原单日期输入替换为mat-date-range-input范围输入组件,绑定表单组和起止控件,保留原有的多年起始视图、月份选中事件配置:

<mat-form-field appearance="fill">
  <mat-label>年月范围</mat-label>
  <mat-date-range-input [rangePicker]="dp" [formGroup]="dateRange">
    <input matStartDate formControlName="start" placeholder="开始月份">
    <input matEndDate formControlName="end" placeholder="结束月份">
  </mat-date-range-input>
  <mat-hint>MM/YYYY – MM/YYYY</mat-hint>
  <mat-datepicker-toggle matSuffix [for]="dp"></mat-datepicker-toggle>
  <mat-date-range-picker #dp
                  startView="multi-year"
                  (monthSelected)="setMonthAndYear($event, dp)"
                  panelClass="month-range-picker-panel">
  </mat-date-range-picker>
</mat-form-field>

3. 可选样式优化

如果需要屏蔽日期面板的日级选择能力,避免用户误操作,可以添加如下样式隐藏日单元格的点击响应:

.month-range-picker-panel .mat-calendar-period-button,
.month-range-picker-panel .mat-calendar-arrow {
  display: none;
}

.month-range-picker-panel .mat-calendar-body-cell {
  pointer-events: none;
}

实现说明:选中的年月范围可直接通过this.dateRange.value获取,返回的start和end均为Moment实例,可直接调用Moment API做后续的格式化、时长计算等处理。如果需要默认打开面板直接进入月选择层级,保留startView="multi-year"配置即可。

内容的提问来源于stack exchange,提问作者Irakli925

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 22:48:36