Angular Material毫秒时间输入在iOS端无法输入秒和毫秒的解决方法
解决iOS端Angular matInput time类型无法输入秒和毫秒的问题
iOS Safari的原生time类型输入控件存在实现限制,即使设置了step="0.001",也不会提供秒和毫秒的输入区域,只能输入小时和分钟。要解决这个问题,最可靠的方式是放弃原生time控件,改用自定义文本输入框并手动处理格式验证,具体实现如下:
方案1:自定义文本输入框(基础版)
模板代码
<mat-form-field appearance="fill" class="full-width"> <mat-label>Lap time</mat-label> <input matInput required name="lapTime" [(ngModel)]="lap_time" type="text" placeholder="HH:mm:ss.SSS" (input)="formatLapTime($event)" /> <mat-error *ngIf="!isValidLapTime(lap_time)">请输入有效格式(如 01:23:45.678)</mat-error> </mat-form-field>
组件逻辑代码
lap_time: string = ''; // 实时格式化输入内容,限制合法字符与格式 formatLapTime(event: Event) { const input = event.target as HTMLInputElement; // 只保留数字、冒号和小数点 let value = input.value.replace(/[^0-9:.]/g, ''); // 按格式拆分并限制各部分长度:HH:mm:ss.SSS const parts = value.split(':'); if (parts.length > 3) parts.splice(3); // 最多保留3段(时、分、秒+毫秒) // 限制小时为2位 if (parts[0]) parts[0] = parts[0].slice(0, 2); // 限制分钟为2位 if (parts[1]) parts[1] = parts[1].slice(0, 2); // 处理秒和毫秒:秒2位,毫秒3位 if (parts[2]) { const secMs = parts[2].split('.'); secMs[0] = secMs[0].slice(0, 2); if (secMs[1]) secMs[1] = secMs[1].slice(0, 3); parts[2] = secMs.join('.'); } input.value = parts.join(':'); this.lap_time = input.value; } // 验证输入格式是否符合 HH:mm:ss.SSS isValidLapTime(value: string): boolean { if (!value) return false; const timeRegex = /^([0-1]\d|2[0-3]):([0-5]\d):([0-5]\d)\.\d{3}$/; return timeRegex.test(value); }
方案2:结合响应式表单(更规范)
如果项目使用Angular响应式表单,可以配合表单验证器实现更严谨的校验:
组件逻辑代码
import { Component } from '@angular/core'; import { FormBuilder, Validators } from '@angular/forms'; @Component({ // 组件元数据... }) export class LapTimeComponent { lapTimeForm = this.fb.group({ lapTime: [ '', [ Validators.required, Validators.pattern(/^([0-1]\d|2[0-3]):([0-5]\d):([0-5]\d)\.\d{3}$/) ] ] }); constructor(private fb: FormBuilder) {} formatLapTime(event: Event) { // 复用方案1中的格式化逻辑 const input = event.target as HTMLInputElement; let value = input.value.replace(/[^0-9:.]/g, ''); const parts = value.split(':'); if (parts.length > 3) parts.splice(3); if (parts[0]) parts[0] = parts[0].slice(0, 2); if (parts[1]) parts[1] = parts[1].slice(0, 2); if (parts[2]) { const secMs = parts[2].split('.'); secMs[0] = secMs[0].slice(0, 2); if (secMs[1]) secMs[1] = secMs[1].slice(0, 3); parts[2] = secMs.join('.'); } input.value = parts.join(':'); this.lapTimeForm.patchValue({ lapTime: input.value }); } }
模板代码
<mat-form-field appearance="fill" class="full-width"> <mat-label>Lap time</mat-label> <input matInput formControlName="lapTime" type="text" placeholder="HH:mm:ss.SSS" (input)="formatLapTime($event)" /> <mat-error *ngIf="lapTimeForm.get('lapTime')?.hasError('required')">此字段必填</mat-error> <mat-error *ngIf="lapTimeForm.get('lapTime')?.hasError('pattern')">请输入有效格式(如 01:23:45.678)</mat-error> </mat-form-field>
补充说明
如果需要更友好的选择器体验(而非纯文本输入),可以自行实现弹窗式的时间选择组件,拆分出时、分、秒、毫秒的下拉选择项,不过开发量会相对较大。
内容的提问来源于stack exchange,提问作者Gabbodrummer
相关产品推荐
相关产品推荐

