Angular:如何获取*ngFor生成的动态输入字段的所有值?
问题诊断
你的代码核心问题是动态生成的表单控件命名不匹配:
- 模板中
*ngFor的index从0开始,所以formControlName="{{ 'customer' + i }}"会生成customer0、customer1... - 但组件初始化时你给FormGroup添加的是
customer1,addCustomer方法里添加的是customer2、customer3... - 这种命名错位导致模板绑定的控件和FormGroup里的控件完全不对应,自然获取不到值。
另外,用FormGroup单独管理多个同类型的动态控件不够高效,Angular的FormArray才是处理这类动态列表控件的标准方案。
解决方案一:修正现有代码的命名匹配
只需要调整模板里的控件命名,让它和组件中添加的控件名一致:
修改HTML模板
把formControlName="{{ 'customer' + i }}"改成formControlName="{{ 'customer' + (i+1) }}",让i从0开始的索引对应customer1、customer2... 和组件里的命名逻辑对齐:
<div fxLayout="row span" fxFlex.gt-sm="50" class="pr-20"> <ng-container *ngFor="let item of [].constructor(customerNumber); let i = index; let isLast = last"> <mat-form-field appearance="outline" fxFlex="80"> <mat-label>Customer</mat-label> <autocomplete-input-field formControlName="{{ 'customer' + (i+1) }}" required [options]="customers" [getOptionIdFunction]="getCustomerId" [getOptionLabelFunction]="getCustomerName" > </autocomplete-input-field> <mat-icon matSuffix class="secondary-text">account_circle</mat-icon> </mat-form-field> <button *ngIf="isLast" mat-icon-button style="margin-top: 10px" color="primary" (click)="addCustomer()"> <mat-icon>add</mat-icon> </button> </ng-container> </div>
获取所有客户值
现在可以通过遍历FormGroup的控件,筛选出以customer开头的控件值:
getAllCustomerValues(): any[] { return Object.entries(this.form.controls) .filter(([key]) => key.startsWith('customer')) .map(([_, control]) => control.value) .filter(value => value); // 过滤空值 }
解决方案二:改用FormArray(推荐)
FormArray专门用于管理一组同类型的表单控件,代码更简洁,也更符合Angular表单的最佳实践:
修改组件TS代码
export class CustomerHistoryMetricsComponent implements OnInit, OnDestroy { @ViewChild('downloadLink', {static: true}) private downloadLink: ElementRef; private _unsubscribeAll: Subject<any>; downloadingExcel: boolean; date = new FormControl(moment()); yearSelected: number; monthSelected: number; customers: Customer[]; form: FormGroup; constructor( private _fuseTranslationLoaderService: FuseTranslationLoaderService, private customerService: CustomerService, private formBuilder: FormBuilder, private metricsService: MetricsService, private fileService: FileService, ) { this._fuseTranslationLoaderService.loadTranslations(english, catalan, spanish); } ngOnInit(): void { this._unsubscribeAll = new Subject(); this.downloadingExcel = false; // 初始化表单,用FormArray管理客户控件 this.form = this.formBuilder.group({ customers: this.formBuilder.array([ this.formBuilder.control('', Validators.required) // 初始一个客户控件 ]), startDate: ['', Validators.required], }); this.customerService.getAllActiveAndAllowedByPermission(Permission.CONSULT_CUSTOMERS) .pipe(takeUntil(this._unsubscribeAll)) .subscribe(customers => { this.customers = customers; }); } // 封装获取customers FormArray的方法 get customersArray(): FormArray { return this.form.get('customers') as FormArray; } ngOnDestroy(): void { this._unsubscribeAll.next(); this._unsubscribeAll.complete(); } public getCustomerId(customer: Customer): number { return customer.id; } public getCustomerName(customer: Customer): string { return customer.name; } public addCustomer(): void { // 给FormArray添加新的控件 this.customersArray.push(this.formBuilder.control('', Validators.required)); } // 获取所有客户值 getAllCustomerValues(): any[] { return this.customersArray.value.filter(value => value); } }
修改HTML模板
用formArrayName和[formControl]绑定FormArray的控件:
<div fxLayout="row span" fxFlex.gt-sm="50" class="pr-20" formArrayName="customers"> <ng-container *ngFor="let control of customersArray.controls; let i = index; let isLast = last"> <mat-form-field appearance="outline" fxFlex="80"> <mat-label>Customer</mat-label> <autocomplete-input-field [formControl]="control" required [options]="customers" [getOptionIdFunction]="getCustomerId" [getOptionLabelFunction]="getCustomerName" > </autocomplete-input-field> <mat-icon matSuffix class="secondary-text">account_circle</mat-icon> </mat-form-field> <button *ngIf="isLast" mat-icon-button style="margin-top: 10px" color="primary" (click)="addCustomer()"> <mat-icon>add</mat-icon> </button> </ng-container> </div>
为什么推荐FormArray?
- 无需手动管理控件命名,彻底避免命名错位问题
- 可以直接通过
customersArray.value获取所有客户值,无需额外筛选 - 支持批量添加/删除控件,表单状态管理更便捷
内容的提问来源于stack exchange,提问作者Santiago Luca
相关产品推荐
相关产品推荐

