You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 01:08:12