Angular模板输入框无法同步FormGroup模型值问题排查
问题:Angular中基于JSON Schema动态生成的FormGroup无法响应模板值变化
相关代码
1. JSON Schema解析生成FormGroup的方法
private parse(shema: object, required: boolean = true) { if (shema["type"] === "string") { return new FormControl( shema["value"] || "", (required)? Validators.required : null) } if (shema["type"] === "boolean") { return new FormControl( shema["value"] || false, (required)? Validators.required : null) } if (shema["type"].length && shema["type"][0] === "limit") { return new FormControl( shema["value"] || "", (required)? Validators.required : null) } if ( shema["type"] === "object" && shema["properties"] ) { let currentLevelControls = new FormGroup({}) for (let propName in shema["properties"]) { const requiredField = (shema["required"][propName])? true : false const parsedResult = this.parse( shema["properties"][propName], requiredField, ) currentLevelControls.controls[propName] = parsedResult } return currentLevelControls } }
2. 组件初始化代码
public configurationForm: FormGroup ... ngOnInit() { this.configurationForm = this.parse(this.jsonShema) as FormGroup this.configurationForm.valueChanges.subscribe((event) => { console.log(event) }) }
3. 模板代码
<div> <div class="modal-header"> <tc-button model="action" icon="close" class="close" (click)="modalClose()"></tc-button> <h4 class="modal-title"> JSON Editor</h4> </div> <form [formGroup]="configurationForm" (change)="onCreateConfiguration($event)"> <div class="modal-body"> <div *ngFor="let item1 of jsonShema['properties'] | keyvalue"> <ng-container *ngIf="item1.value.type === 'object'" [formGroupName]="item1.key"> <h5>{{item1.key}}</h5> <div *ngFor="let item2 of item1.value.properties | keyvalue"> <ng-container *ngIf="item2.value.type === 'boolean'"> <div class="checkbox"> <mat-checkbox [formControlName]="item2['key']">{{item2.key}}</mat-checkbox> </div> </ng-container> <ng-container *ngIf="item2.value.type === 'string'"> <mat-form-field > <input type="text" [formControlName]="item2['key']" matInput [placeholder]="item2.key" required> </mat-form-field> </ng-container> <ng-container *ngIf="item2.value.type.length && item2.value.type[0] === 'limit'"> <mat-form-field> <input type="text" [formControlName]="item2['key']" matInput [placeholder]="item2.key" required> </mat-form-field> </ng-container> </div> </ng-container> </div> </div> <div class="modal-footer"> <tc-button type="button" color="neutral">Cancel</tc-button> <tc-button type="submit" (click)="!configurationForm?.invalid && onCreateConfiguration()">Create</tc-button> </div> </form> </div>
问题现象
表单渲染正常,但修改输入内容时,valueChanges事件不触发,form.value及touched、pristine等状态均无变化。
已做排查:
- 检查发现HTML中未渲染
formcontrolname="value"属性,改为formControlName="item2['key']"会被识别为固定值并报错,确认FormGroup与模板绑定逻辑无误; - 改用
FormGroup.addControl()方法生成两层结构的表单,问题仍存在,怀疑模板端有问题。
解决方案
1. 修正模板中formControlName绑定错误
模板里的[formControlName]="item2['key']"写法错误,item2是keyvalue管道返回的对象,键名直接通过item2.key访问即可,不需要字符串索引:
<!-- 布尔类型控件 --> <mat-checkbox [formControlName]="item2.key">{{item2.key}}</mat-checkbox> <!-- 字符串类型控件 --> <input type="text" [formControlName]="item2.key" matInput [placeholder]="item2.key" required> <!-- limit类型控件 --> <input type="text" [formControlName]="item2.key" matInput [placeholder]="item2.key" required>
2. 修正FormGroup控件添加方式
直接给currentLevelControls.controls[propName]赋值不符合Angular表单API规范,Angular无法检测到这种方式添加的控件,必须使用addControl方法:
if ( shema["type"] === "object" && shema["properties"] ) { let currentLevelControls = new FormGroup({}) for (let propName in shema["properties"]) { // JSON Schema的required是数组,修正必填判断逻辑 const requiredField = shema["required"]?.includes(propName) ?? false; const parsedResult = this.parse( shema["properties"][propName], requiredField, ) // 使用addControl添加子控件 currentLevelControls.addControl(propName, parsedResult); } return currentLevelControls }
3. 额外优化点
- 移除
<form>标签上的(change)事件,避免与valueChanges监听冲突; - 确认
jsonShema的required字段为字符串数组(符合JSON Schema规范); - 确保Angular Material组件已正确导入并在模块中声明。
内容的提问来源于stack exchange,提问作者Lynxara
相关产品推荐
相关产品推荐

