Angular13+中AbstractControl不存在controls属性的修复方案咨询
Angular 13+ 响应式表单
Property 'controls' does not exist on type 'AbstractControl<any, any>' 修复方案 问题根源
Angular 13+ 强化了表单控件的类型检查,AbstractControl 基类并不包含 controls 属性,只有 FormGroup 和 FormArray 子类才有该属性。之前的代码直接通过 AbstractControl 实例访问 controls,在严格类型检查下会触发报错。
TypeScript代码修复
修改两处核心逻辑,避免直接访问 controls 属性,改用类型断言或 get() 方法:
sumOfOwed方法:遍历FormArray时,将每个AbstractControl断言为FormGroup,同时添加空值保护避免报错:
sumOfOwed() { this.items = this.form.get('items') as FormArray; this.sum = 0; this.items.controls.forEach((control) => { const itemGroup = control as FormGroup; this.sum += itemGroup.get('owedInDollars')?.value || 0; this.totalsum = this.sum; }); console.log(`Total Owed in Dollars: ${this.sum}`); }
selectOption方法:用get()方法替代直接访问item.controls,遍历控件时添加类型断言:
selectOption(item: FormGroup, option: string) { item.get('dispute')?.setValue(option === 'dispute' ? 'dispute' : ''); item.get('return')?.setValue(option === 'return' ? 'return' : ''); item.get('takePayment')?.setValue(option === 'takePayment' ? 'takePayment' : ''); let total = 0; this.items.controls.forEach((control) => { const itemGroup = control as FormGroup; const owed = itemGroup.get('owedInDollars')?.value || 0; const disputeVal = itemGroup.get('dispute')?.value; const returnVal = itemGroup.get('return')?.value; if (disputeVal || returnVal) { total += owed; } }); console.log(`New Total Owed in Dollars: ${this.sum - total}`); this.totalsum = this.sum - total; }
HTML模板修复
模板中直接访问 item.controls 会触发类型错误,改用 get() 方法访问控件值,同时调用方法时添加类型断言:
<form [formGroup]="form"> <table id="customers"> <thead> <tr> <th>Device Name</th> <th>Model Number</th> <th>Serial Number</th> <th>Dispute</th> <th>Return</th> <th>Take Payment</th> <th>Owed in Dollars</th> </tr> </thead> <tbody formArrayName="items"> <tr *ngFor="let item of items.controls; let i=index" [formGroupName]="i"> <td>{{ item.get('deviceName')?.value }}</td> <td>{{ item.get('modelNumber')?.value }}</td> <td>{{ item.get('serialNumber')?.value }}</td> <td><input type="radio" formControlName="dispute" value="dispute" (click)="selectOption(item as FormGroup, 'dispute')"></td> <td><input type="radio" formControlName="return" value="return" (click)="selectOption(item as FormGroup, 'return')"></td> <td><input type="radio" formControlName="takePayment" value="takePayment" (click)="selectOption(item as FormGroup, 'takePayment')" [checked]="true"></td> <td>{{ item.get('owedInDollars')?.value }}</td> </tr> <tr *ngFor="let item of items.controls; let i=index" [formGroupName]="i"> <td colspan="7" *ngIf="item.get('dispute')?.value"> <label>Reason:</label> <select formControlName="reason"> <option value="">--Select--</option> <option value="Damaged">Damaged</option> <option value="Wrong Item">Wrong Item</option> <option value="Missing Part">Missing Part</option> <option value="Other">Other</option> </select> </td> </tr> </tbody> </table> </form> <div><h2>{{totalsum}}</h2></div>
额外优化建议
可以在组件中添加一个 getter 方法,简化 FormArray 的类型转换:
get itemsArray(): FormArray { return this.form.get('items') as FormArray; }
之后模板和TS代码中都可以用 this.itemsArray 替代 this.items,减少重复的类型断言逻辑。
内容的提问来源于stack exchange,提问作者Teja
相关产品推荐
相关产品推荐

