Angular 8 FormArray索引数据未更新

问题描述

我正在尝试根据具有填充内容的初始数据从组中创建动态对象,并从组中添加/删除。不幸的是,它无法正常工作。

预期的行为是

  • Coutry下拉菜单将加载数据,并以选定的值突出显示,这已经可以正常工作了。
  • 认情况下,应使用从初始数据stateCode中选择的值来加载“选择的国家/地区”下拉数据,并且在更改当前也不可用的国家/地区时。
  • 在单击添加按钮时,认情况下应加载“美国”国家/地区和相应州的数据。认情况下,“状态”下拉列表应使用“ --select--”进行选择。

注意:所有数据将来自API。为了测试目的,我为国家和州添加了静态对象。

enter image description here

这是我的尝试

https://stackblitz.com/edit/angular-8-app-example-fkjzfe-wekubn?file=src%2Fapp%2Fapp.component.ts

当前行为演示

https://angular-8-app-example-fkjzfe.stackblitz.io/

HTML

  <form [formGroup]='entityForm'>
              <div formArrayName="optionGroups" class="ui-g ui-g-12 ui-g-nopad " >
                <div  style="width: 100%;
    display: flex; margin-bottom:10px" class="ui-g  ui-g-12 ui-g-nopad " *ngFor="let item of entityForm.controls['optionGroups'].controls; let $index=index" [formGroup]="item">        
                  <div class="ui-md-4">                   
                    <label class="mandatory"
                  >Country
                  <span class="colon"></span>
                </label>
                <select formControlName="country" class="ui-inputtext" (change)="onCountryChange(entityForm.controls['optionGroups'].controls[$index].controls['country'].value,$index)" > 
                  <option>--Select--</option>
                  <option *ngFor="let c of countries" [ngValue]="c.countryCode">{{c.country}}</option>                 
                </select>
              </div>
              <div class="ui-md-4">

                <label class="lbl-hidden"> State </label>
                <select formControlName="state" class="ui-inputtext"> 
                  <option>--Select--</option>
                  <option *ngFor="let state of states[entityForm.controls['optionGroups'].controls[$index].controls['country'].value]" value="state.code">{{state.state}}</option>
              </select>
              </div>
              <div class="ui-md-3">
                <label class="lbl-hidden"> Number </label>
                <input
                  type="text"
                  pInputText
                  class="form-control"
                  formControlName="place"    
                />
                </div>
                <div class="ui-md-1">
                 
                  <button (click)='removeOptionGroup(i)'  style="min-width: auto;"  pButton icon="fa fa-minus">Remove</button>
                </div>
                </div>
              </div>
            </form>        
            <button class="add-remove-btn" pButton (click)='addOptionGroup()' icon="fa fa-plus">Add</button>` 

TS

import { Component,OnInit,ViewChild } from '@angular/core'

import { FormBuilder,Validators,FormArray,FormGroup,FormControl } from '@angular/forms';

@Component({
  selector: 'my-app',templateUrl: './app.component.html',styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit  {
  public countryOptions:any = [];
  public stateOptions:any = [];

  public countries = [];
  public states = [];

  public entityForm: FormGroup;

constructor(private fb: FormBuilder) {
  this.entityForm = this.fb.group({
    optionGroups : this.fb.array([]),});

this.countries = this.countryOptions
this.states=[];
}


public addOptionGroup(){

  const fa = this.entityForm.controls["optionGroups"] as FormArray;
   //fa.setValue("--Select--");
  fa.push(this.newOptionGroup());


  }

  public removeOptionGroup(index: number){

    const fa = this.entityForm.controls["optionGroups"] as FormArray;
  
    fa.removeAt(index);
  
    }

    onCountryChange(selectedCountry: string,formIndex : number) : void {
      this.states[selectedCountry] = this.getStates(selectedCountry)
    }

    private newOptionGroup() {
      return new FormGroup({          
          country: new FormControl("--select--"),state: new FormControl("--select--"),place: new FormControl("GGG"),});
  }


  getStates(selectedCountry) {
    //API call

    switch(selectedCountry) {
      case "US" : 
        this.stateOptions =[
      {id: 14,state: "Alabama",code: "AL",countryCode: "US"},{id: 15,state: "Alaska",code: "AK",{id: 17,state: "Arizona",code: "AZ",{id: 18,state: "Arkansas",code: "AR",{id: 19,state: "California",code: "CA",countryCode: "US"}
      ]
      break;

     case  "CA" :
       this.stateOptions =[{id: 37,state: "Marshall Islands",code: "MH",countryCode: "CA"},{id: 4,state: "New Brunswick",code: "NB",{id: 5,state: "Newfoundland and Labrador",code: "NL",{id: 53,state: "northern Mariana Islands",code: "MP",{id: 6,state: "northwest Territories",code: "NT",countryCode: "CA"}]
      break;    
    default: 
     this.stateOptions =[
      {id: 14,countryCode: "US"}
      ]
      break;
  }
    return this.stateOptions;

   }

   initFormArray(initForm:any) {
    const formArray = this.entityForm.get('optionGroups') as FormArray;
    initForm.map((item,index) => {
      formArray.push(this.createForms(item,index));
    });
    this.entityForm.setControl('optionGroups',formArray);
   }

   createForms(adresse,index): FormGroup {
   
    let formGroup: FormGroup = new FormGroup(
      {
        country: new FormControl(adresse.countryCode),state: new FormControl(adresse.stateCode),place: new FormControl(adresse.fileNumber)
      }
    );
 this.onCountryChange(adresse.select1,index)
    return formGroup;
  }


  
 getAllCountries() {
   //API call
   this.countries = [{"country":"United States","countryCode":"US"},{"country":"Canada","countryCode":"CA"}]
 }
  

  ngOnInit() {
    this.getAllCountries()
    const initData = [
      {countryCode: "US",stateCode: "AZ",fileNumber: "AAA"},{countryCode: "CA",stateCode: null,fileNumber: null}
    ]

    this.initFormArray(initData)
  }

}

解决方法

我简化了您的脚本,似乎可以正常工作。但这还没有结束-可能会做得更漂亮。请注意html的组成部分-[formGroupName] =“ i”以及如何使用formArray变量。

//html
<form [formGroup]="entityForm">
  <div formArrayName="optionGroups" class="ui-g ui-g-12 ui-g-nopad">
    <ng-container *ngFor="let item of optionGroups.controls; let i = index;" [formGroupName]="i">
      <div style="width: 100%; display: flex; margin-bottom:10px" class="ui-g  ui-g-12 ui-g-nopad">
        <div class="ui-md-4">
          <label class="mandatory">Country <span class="colon"></span></label>
          <select 
            formControlName="country"
            class="ui-inputtext" 
            (change)="onCountryChange(item.get('country').value,i)" 
            > 
            <option>--Select--</option>
            <option *ngFor="let c of countries" [ngValue]="c.countryCode">{{c.country}}</option>                 
          </select>
        </div>

        <div class="ui-md-4">
          <label class="lbl-hidden"> State </label>
          <select formControlName="state" class="ui-inputtext"> 
            <option>--Select--</option>
            <option *ngFor="let state of getStates(item.controls['country'].value)" [ngValue]="state.code">{{state.state}}</option>
          </select>
        </div>

        <div class="ui-md-3">
          <label class="lbl-hidden"> Number </label>
          <input
            type="text"
            pInputText
            class="form-control"
            formControlName="place"    
          />
        </div>
        <div class="ui-md-1">     
          <button (click)='removeOptionGroup(i)'  style="min-width: auto;"  pButton icon="fa fa-minus">Remove</button>
        </div>
      </div>
    </ng-container>
  </div>
</form>
<button class="add-remove-btn" pButton (click)='addOptionGroup()' icon="fa fa-plus">Add</button>

//ts
public countryOptions:any = [];
  public stateOptions:any = [];

  public countries = [];
  public states = [];

  public entityForm: FormGroup;
  public optionGroups: FormArray;

  constructor(
    private fb: FormBuilder
    ) {}

  ngOnInit() {
    this.entityForm = this.fb.group({
      optionGroups : this.fb.array([])
    });

    this.optionGroups = this.entityForm.get('optionGroups') as FormArray;

    this.getAllCountries();
    const initData = [
      {countryCode: "US",stateCode: "AZ",fileNumber: "AAA"},{countryCode: "CA",stateCode: null,fileNumber: null}
    ]

    this.initFormArray(initData)
  }


  public addOptionGroup(){
    const fa = this.entityForm.get('optionGroups') as FormArray;
    //fa.setValue("--Select--");
    fa.push(this.newOptionGroup());
  }

  public removeOptionGroup(index: number){

      const fa = this.entityForm.controls["optionGroups"] as FormArray;
    
      fa.removeAt(index);
    
      }

  onCountryChange(selectedCountry: string,formIndex : number) : void {
    console.log(selectedCountry);
    this.states[selectedCountry] = this.getStates(selectedCountry)
  }

  private newOptionGroup() {
    return new FormGroup({          
        country: new FormControl("--select--"),state: new FormControl("--select--"),place: new FormControl("GGG"),});
  }


  getStates(selectedCountry) {
    //API call

      switch(selectedCountry) {
        case "US" : 
          this.stateOptions =[
        {id: 14,state: "Alabama",code: "AL",countryCode: "US"},{id: 15,state: "Alaska",code: "AK",{id: 17,state: "Arizona",code: "AZ",{id: 18,state: "Arkansas",code: "AR",{id: 19,state: "California",code: "CA",countryCode: "US"}
        ]
        break;

      case  "CA" :
        this.stateOptions =[{id: 37,state: "Marshall Islands",code: "MH",countryCode: "CA"},{id: 4,state: "New Brunswick",code: "NB",{id: 5,state: "Newfoundland and Labrador",code: "NL",{id: 53,state: "Northern Mariana Islands",code: "MP",{id: 6,state: "Northwest Territories",code: "NT",countryCode: "CA"}]
        break;    
      default: 
      this.stateOptions =[
        {id: 14,countryCode: "US"}
        ]
        break;
    }
    return this.stateOptions;
  }

  initFormArray(initForm:any) {
    console.log(initForm);
    initForm.map((item,index) => {
      this.optionGroups.push(this.createForms(item,index));
    });
  }

  createForms(adresse,index): FormGroup {   
    const formGroup = new FormGroup({
        country: new FormControl(adresse.countryCode),state: new FormControl(adresse.stateCode),place: new FormControl(adresse.fileNumber)
      });
    this.onCountryChange(adresse.select1,index);
  return formGroup;
  }

  getAllCountries() {
    //API call
    this.countries = [{"country":"United States","countryCode":"US"},{"country":"Canada","countryCode":"CA"}]
  }