Angular 6中如何实现支持多日期选择的datepicker组件
Angular 6 多日期选择Datepicker实现方案
Angular 6 版本的 Material Datepicker 未提供 Angular 7+ 才支持的dateClass输入属性,无法直接复用高版本基于dateClass的多选实现,可通过自定义日历单元格+接管选择事件的方式实现同等效果,无需升级框架版本。
核心实现逻辑
绕过高版本专属的dateClass接口,直接接管三个核心环节:选中日期的存储、日历单元格的自定义渲染、选中状态的切换逻辑。
分步实现
存储选中日期
在组件中用Set结构存储选中日期,天然去重,同时编写日期匹配方法,对比时统一抹平时分秒差异,仅校验年月日:import { Component, ChangeDetectorRef } from '@angular/core'; import { MatDatepickerInputEvent } from '@angular/material/datepicker'; @Component({ selector: 'app-multi-date-picker', templateUrl: './multi-date-picker.component.html', styleUrls: ['./multi-date-picker.component.css'] }) export class MultiDatePickerComponent { selectedDates = new Set<Date>(); constructor(private cdr: ChangeDetectorRef) {} isDateSelected(date: Date): boolean { const targetStamp = new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime(); return Array.from(this.selectedDates).some(item => { const itemStamp = new Date(item.getFullYear(), item.getMonth(), item.getDate()).getTime(); return itemStamp === targetStamp; }); } }自定义日历单元格渲染
Angular 6 支持通过*matDatepickerCalendarCell结构指令自定义每个日历单元格的内容和样式,给选中状态的日期加高亮类即可替代dateClass的样式标记能力:<mat-form-field appearance="fill"> <input matInput [matDatepicker]="multiPicker" placeholder="选择多个日期" (dateChange)="handleDateSelect($event)" > <mat-datepicker-toggle matSuffix [for]="multiPicker"></mat-datepicker-toggle> <mat-datepicker #multiPicker> <!-- 自定义日历单元格 --> <mat-calendar-cell *matDatepickerCalendarCell="let currentDate"> <div class="date-cell" [class.is-selected]="isDateSelected(currentDate)"> {{currentDate.getDate()}} </div> </mat-calendar-cell> </mat-datepicker> </mat-form-field>配套单元格样式:
.date-cell { width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; border-radius: 50%; cursor: pointer; } .date-cell.is-selected { background: #1976d2; color: #fff; }接管日期选择逻辑
监听输入框的dateChange事件,拦截默认的单选赋值逻辑,点击日期时切换选中状态,同时手动触发变更检测刷新日历样式:handleDateSelect(event: MatDatepickerInputEvent<Date>) { if (!event.value) return; // 统一抹平时间部分 const clickedDate = new Date( event.value.getFullYear(), event.value.getMonth(), event.value.getDate() ); // 切换选中状态:已选则移除,未选则加入集合 if (this.isDateSelected(clickedDate)) { this.selectedDates.delete(clickedDate); } else { this.selectedDates.add(clickedDate); } // 清空输入框默认单选值,避免显示单个日期 event.target.value = null; // 手动触发变更检测,强制日历重绘更新选中样式 this.cdr.markForCheck(); } // 对外提供获取选中结果的方法 getSelectedDates(): Date[] { return Array.from(this.selectedDates); }
兼容注意点
- 如果项目使用
MomentDateAdapter替代原生Date适配器,日期对比逻辑可直接调用Moment的isSame(day)方法,无需手动拼接时间戳 - 不要修改Datepicker的内部私有属性/方法,避免小版本升级出现兼容问题
- 若需要支持范围选择,可在现有选中逻辑基础上增加起止点标记,无需改动单元格渲染逻辑
内容的提问来源于stack exchange,提问作者leslie
相关产品推荐
相关产品推荐

