Angular动态表单输入框输入单个字符后失焦问题求助
输入框输入单个字符后失焦问题解决方案
我已尝试StackOverflow上所有类似问题的解决方案,但仍无法解决输入框输入单个字符后失去焦点的问题。相关代码如下:
Component.ts 代码
private initForm() { if (this.form) { this.form.patchValue(this.course); } else { var controlsConfig = { duration: [this.course.duration], credits: [this.course.credits], expires: [], comment: [this.course.comment] }; // 添加自定义字段到表单控件 for (var i = 0; i < this.courseCustomFields.length; i++) { controlsConfig[this.courseCustomFields[i].key] = [this.course[this.courseCustomFields[i].key]]; } this.form = this.formBuilder.group(controlsConfig); } }
Component.html 代码
<div class="row" *ngFor="let courseCustomFieldRow of courseCustomFieldsForFront"> <div class="col-md-3" *ngFor="let courseCustomField of courseCustomFieldRow"> <div class="form-group"> <label>{{courseCustomField.title}}</label> <input type="text" class="form-control" [formControlName]="courseCustomField.key"> </div> </div> </div>
问题排查与解决办法
1. 为*ngFor添加trackBy函数
Angular的*ngFor默认依赖对象引用追踪DOM元素,当表单值更新时,若courseCustomFieldsForFront或内部对象被重新创建,Angular会销毁并重建所有循环生成的DOM节点,直接导致输入框失焦。
解决步骤:
- 在组件类中添加
trackBy函数:trackByCustomField(index: number, field: any): string { return field.key; // 使用自定义字段的唯一key作为追踪标识 } - 修改模板中的循环语句:
<div class="row" *ngFor="let courseCustomFieldRow of courseCustomFieldsForFront; trackBy: trackByCustomField"> <div class="col-md-3" *ngFor="let courseCustomField of courseCustomFieldRow; trackBy: trackByCustomField"> <!-- 原有输入框代码不变 --> </div> </div>
2. 避免initForm重复触发
若initForm在输入过程中被意外调用(比如组件变更检测时重复执行),会导致表单被重新构建或执行patchValue,触发DOM重渲染。
解决步骤:
- 检查
initForm的调用时机,确保仅在组件初始化或course/courseCustomFields首次变更时执行,例如结合ngOnChanges:import { SimpleChanges, OnChanges, OnInit } from '@angular/core'; // 组件类实现OnChanges接口 ngOnChanges(changes: SimpleChanges) { if ((changes['course'] && !changes['course'].firstChange) || (changes['courseCustomFields'] && !changes['courseCustomFields'].firstChange)) { if (this.form) { this.form.patchValue(this.course); } else { this.initForm(); } } } ngOnInit() { this.initForm(); }
3. 替换var为let避免作用域问题
原循环中使用var i存在函数作用域污染风险,虽然不直接引发失焦,但建议替换为块级作用域的let,减少潜在问题:
for (let i = 0; i < this.courseCustomFields.length; i++) { controlsConfig[this.courseCustomFields[i].key] = [this.course[this.courseCustomFields[i].key]]; }
内容的提问来源于stack exchange,提问作者Dula
相关产品推荐
相关产品推荐

