Angular中如何动态移除MAT_DATE_RANGE_SELECTION_STRATEGY自定义策略
Angular Material 日期范围选择器动态切换选择策略问题
我正在Angular中实现一个日期选择器,通过自定义MAT_DATE_RANGE_SELECTION_STRATEGY限制用户只能选择14天的日期范围。
我参考Angular官方文档编写了如下自定义策略代码:
@Injectable() export class FourteenDayRangeSelectionStrategy<D> implements MatDateRangeSelectionStrategy<D> { constructor(private _dateAdapter: DateAdapter<D>) {} selectionFinished(date: D | null): DateRange<D> { return this._createFourteeDayRange(date); } createPreview(activeDate: D | null): DateRange<D> { return this._createFourteeDayRange(activeDate); } private _createFourteeDayRange(date: D | null): DateRange<D> { if (date) { const start = this._dateAdapter.addCalendarDays(date, 0); const end = this._dateAdapter.addCalendarDays(date, 13); return new DateRange<D>(start, end); } return new DateRange<D>(null, null); } }
并通过组件providers将该策略注入,代码如下:
@Component({ selector: 'app-awesomecomponent', templateUrl: './awesomecomponent.component.html', styleUrls: ['./awesomecomponent.component.css'], providers: [{ provide: MAT_DATE_RANGE_SELECTION_STRATEGY, useClass: FourteenDayRangeSelectionStrategy }] })
现在我需要实现如下功能:当用户勾选「允许自定义日期范围」复选框时,禁用上述自定义策略,允许用户选择任意长度的日期范围。
我原本以为只要动态移除组件providers中对应的MAT_DATE_RANGE_SELECTION_STRATEGY配置即可实现,但不清楚具体操作方法,请问该如何实现这一需求?
解决方案
Angular 组件的 providers 配置是编译时确定的,运行时无法动态增删,不需要修改 providers 配置,直接改造自定义策略增加控制开关即可实现需求,步骤如下:
- 修改自定义策略类,增加控制开关和默认选择逻辑的兼容处理,同时修正原代码中
Fourteen的拼写错误:
@Injectable() export class FourteenDayRangeSelectionStrategy<D> implements MatDateRangeSelectionStrategy<D> { // 控制是否允许自定义范围的开关 allowCustomRange = false; // 存储自定义范围选择时的起始日期 private _selectedStart: D | null = null; constructor(private _dateAdapter: DateAdapter<D>) {} selectionFinished(date: D | null): DateRange<D> { // 允许自定义范围时走默认选择逻辑 if (this.allowCustomRange) { if (!this._selectedStart) { // 第一次点击选起始日期 this._selectedStart = date; return new DateRange<D>(date, null); } else { // 第二次点击选结束日期,清空起始日期缓存 const range = new DateRange<D>(this._selectedStart, date); this._selectedStart = null; return range; } } // 否则走14天固定范围逻辑 return this._createFourteenDayRange(date); } createPreview(activeDate: D | null): DateRange<D> { if (this.allowCustomRange && this._selectedStart) { // 自定义范围预览时显示从起始日期到当前hover日期的范围 return new DateRange<D>(this._selectedStart, activeDate); } return this._createFourteenDayRange(activeDate); } private _createFourteenDayRange(date: D | null): DateRange<D> { if (date) { const start = this._dateAdapter.addCalendarDays(date, 0); const end = this._dateAdapter.addCalendarDays(date, 13); return new DateRange<D>(start, end); } return new DateRange<D>(null, null); } }
- 在组件中注入策略实例,绑定复选框状态修改开关值:
组件类代码:
import { MAT_DATE_RANGE_SELECTION_STRATEGY } from '@angular/material/datepicker'; @Component({ selector: 'app-awesomecomponent', templateUrl: './awesomecomponent.component.html', styleUrls: ['./awesomecomponent.component.css'], providers: [{ provide: MAT_DATE_RANGE_SELECTION_STRATEGY, useClass: FourteenDayRangeSelectionStrategy }] }) export class Awesomecomponent { // 注入策略实例 constructor( @Inject(MAT_DATE_RANGE_SELECTION_STRATEGY) private rangeStrategy: FourteenDayRangeSelectionStrategy<Date> ) {} // 复选框change事件处理 onCustomRangeToggle(checked: boolean) { this.rangeStrategy.allowCustomRange = checked; // 切换时清空缓存的起始日期,避免状态混乱 this.rangeStrategy['_selectedStart'] = null; } }
模板中复选框绑定示例:
<mat-checkbox (change)="onCustomRangeToggle($event.checked)"> 允许自定义日期范围 </mat-checkbox>
内容的提问来源于stack exchange,提问作者VIRIYALA NARESH
相关产品推荐
相关产品推荐

