Angular 10中如何恢复ngModel日期输入框至之前有效值?
Angular 10 + Nebular 6 日期输入框校验解决方案
方法一:基于ngModel的旧值跟踪(兼容现有模板)
- 组件中维护旧值状态
在组件类里为两个日期分别保存独立的旧值,初始化时同步初始数据:
startOfProject: Date; endOfProject: Date; private _oldStartDate: Date; private _oldEndDate: Date; ngOnInit() { // 示例初始值,可替换为接口返回或业务默认值 this.startOfProject = new Date(); this.endOfProject = new Date(Date.now() + 86400000); // 初始结束日设为次日 // 初始化旧值(必须深拷贝,避免引用同步) this._oldStartDate = new Date(this.startOfProject); this._oldEndDate = new Date(this.endOfProject); }
- 模板绑定规则
保留[(ngModel)]双向绑定,同时绑定(change)事件(避免用ngModelChange,它会在值变更前触发,易引发不可预知的冲突):
<nb-input-group> <input nbInput placeholder="Start of project" [(ngModel)]="startOfProject" [nbDatepicker]="startPicker" (change)="validateStartDate()"> <nb-datepicker #startPicker></nb-datepicker> </nb-input-group> <nb-input-group> <input nbInput placeholder="End of project" [(ngModel)]="endOfProject" [nbDatepicker]="endPicker" (change)="validateEndDate()"> <nb-datepicker #endPicker></nb-datepicker> </nb-input-group>
- 实现校验逻辑
编写校验函数,无效时恢复旧值,有效时更新旧值存储:
validateStartDate() { if (this.startOfProject > this.endOfProject) { // 恢复旧值 this.startOfProject = new Date(this._oldStartDate); } else { // 更新旧值为当前有效值 this._oldStartDate = new Date(this.startOfProject); } } validateEndDate() { if (this.endOfProject < this.startOfProject) { this.endOfProject = new Date(this._oldEndDate); } else { this._oldEndDate = new Date(this.endOfProject); } }
方法二:响应式表单(官方推荐,更易维护)
如果项目允许切换到响应式表单,这是更规范的方案,利用FormControl的valueChanges监听值变化,结合patchValue恢复有效值:
- 初始化表单与监听逻辑
import { FormBuilder, FormGroup } from '@angular/forms'; projectForm: FormGroup; private _oldValues = { startOfProject: null, endOfProject: null }; constructor(private fb: FormBuilder) {} ngOnInit() { this.projectForm = this.fb.group({ startOfProject: [new Date()], endOfProject: [new Date(Date.now() + 86400000)] }); // 初始化旧值 this._oldValues.startOfProject = new Date(this.projectForm.get('startOfProject').value); this._oldValues.endOfProject = new Date(this.projectForm.get('endOfProject').value); // 监听开始日期变化 this.projectForm.get('startOfProject').valueChanges.subscribe(newStart => { if (newStart > this.projectForm.get('endOfProject').value) { // 恢复旧值,emitEvent: false避免循环触发监听 this.projectForm.get('startOfProject').patchValue(this._oldValues.startOfProject, { emitEvent: false }); } else { this._oldValues.startOfProject = new Date(newStart); } }); // 监听结束日期变化 this.projectForm.get('endOfProject').valueChanges.subscribe(newEnd => { if (newEnd < this.projectForm.get('startOfProject').value) { this.projectForm.get('endOfProject').patchValue(this._oldValues.endOfProject, { emitEvent: false }); } else { this._oldValues.endOfProject = new Date(newEnd); } }); }
- 模板绑定响应式表单
<nb-input-group> <input nbInput placeholder="Start of project" formControlName="startOfProject" [nbDatepicker]="startPicker"> <nb-datepicker #startPicker></nb-datepicker> </nb-input-group> <nb-input-group> <input nbInput placeholder="End of project" formControlName="endOfProject" [nbDatepicker]="endPicker"> <nb-datepicker #endPicker></nb-datepicker> </nb-input-group>
关键注意点
- 处理日期必须用
new Date()深拷贝,直接赋值会导致新旧值引用同一个对象,修改时同步变更旧值。 - Nebular的
nb-datepicker返回的是标准Date对象,可直接比较大小,无需额外格式转换。
内容的提问来源于stack exchange,提问作者samax
相关产品推荐
相关产品推荐

