Angular响应式表单如何实现开始/结束时间的格式与大小校验?
Angular响应式表单时分输入校验实现方案
一、TypeScript 逻辑修正
首先补全表单实例持有逻辑,新增单控件格式校验、表单组级别的跨字段时间范围自定义校验器,从规则层限制分钟取值范围、校验时间先后顺序。
import { Component, OnInit } from '@angular/core'; import { FormBuilder, FormGroup, Validators, AbstractControl, ValidationErrors } from '@angular/forms'; @Component({ selector: 'app-time-form', templateUrl: './time-form.component.html' }) export class TimeFormComponent implements OnInit { form: FormGroup; // 自定义跨字段校验器:校验结束时间必须晚于开始时间 timeRangeValidator(formGroup: AbstractControl): ValidationErrors | null { const startTime = formGroup.get('startTime')?.value; const endTime = formGroup.get('endTime')?.value; const timeReg = /^([01]?[0-9]|2[0-3]):([0-5][0-9])$/; // 任意一个字段为空、格式不合法时,不触发跨字段校验,交给单控件校验逻辑处理 if (!startTime || !endTime || !timeReg.test(startTime) || !timeReg.test(endTime)) { return null; } // 将时:分格式转为总分钟数做大小比较 const [startHour, startMinute] = startTime.split(':').map(Number); const [endHour, endMinute] = endTime.split(':').map(Number); const startTotal = startHour * 60 + startMinute; const endTotal = endHour * 60 + endMinute; return endTotal > startTotal ? null : { timeRangeInvalid: true }; } constructor(private formBuilder: FormBuilder) { } ngOnInit(): void { this.form = this.formBuilder.group({ startTime: ['', [ Validators.required, // 正则限制HH:mm格式:小时0-23,分钟0-59,从根本上拦截分钟超过59的非法输入 Validators.pattern(/^([01]?[0-9]|2[0-3]):([0-5][0-9])$/) ]], endTime: ['', [ Validators.required, Validators.pattern(/^([01]?[0-9]|2[0-3]):([0-5][0-9])$/) ]] }, { validators: this.timeRangeValidator }); } }
二、HTML 模板修正
替换原number类型输入框为text类型(支持冒号分隔符输入),补全表单组绑定,添加对应错误提示。
<form [formGroup]="form"> <div class="form-item"> <label>开始时间</label> <input type="text" formControlName="startTime" placeholder="请输入HH:mm格式,例如06:10" /> <!-- 单控件错误提示 --> <div *ngIf="form.get('startTime')?.touched && form.get('startTime')?.invalid" class="error-text"> <span *ngIf="form.get('startTime')?.hasError('required')">开始时间不能为空</span> <span *ngIf="form.get('startTime')?.hasError('pattern')">请输入合法时间格式,分钟取值范围为00-59</span> </div> </div> <div class="form-item"> <label>结束时间</label> <input type="text" formControlName="endTime" placeholder="请输入HH:mm格式,例如18:30" /> <!-- 单控件错误提示 --> <div *ngIf="form.get('endTime')?.touched && form.get('endTime')?.invalid" class="error-text"> <span *ngIf="form.get('endTime')?.hasError('required')">结束时间不能为空</span> <span *ngIf="form.get('endTime')?.hasError('pattern')">请输入合法时间格式,分钟取值范围为00-59</span> </div> </div> <!-- 跨字段校验错误提示 --> <div *ngIf="form.touched && form.hasError('timeRangeInvalid')" class="error-text"> 结束时间必须晚于开始时间 </div> </form>
三、实现说明
- 废弃原
type="number"输入框:HH:mm格式包含冒号非数字字符,number类型输入框本身不支持该类内容输入,不适用于当前场景。 - 分钟取值限制通过正则实现:正则规则直接限定分钟位只能输入00-59,直接拦截分钟超过59的非法值,不需要额外写输入事件拦截逻辑。
- 修正原代码的表单绑定问题:原代码构建FormGroup后没有赋值给类属性,模板无法完成表单绑定,新增
form属性持有构建好的表单实例。 - 跨字段校验挂载在FormGroup层级:只有两个时间字段都通过必填、格式校验后才触发时间先后比较,避免和单控件校验逻辑冲突,错误统一挂载在表单组上方便提示。
- 如果需要更严格的输入体验,可以额外绑定
keydown事件拦截数字、冒号之外的字符输入,现有正则校验已经可以覆盖非法值的拦截和提示需求。
内容的提问来源于stack exchange,提问作者user18158518
相关产品推荐
相关产品推荐

