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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 12:36:20