以 Angular 反应形式显示多个送货地址

Displaying multiple shipping addresses in Angular reactive Form

我正在尝试显示来自 API 的送货地址,目前数据库中有三个地址,但只有一个地址显示了 3 次

这是组件Html代码

<div class="row" formControlName="shippingAddressForm">
                <div class="form-group col-6">
                  <h1 class="h3 mt-4">Shipping Address</h1>
                  <div *ngFor="let item of shippingAddress?.data">
                  <form 
                  [formGroup]='shippingAddressForm'
            (ngSubmit)="Save(shippingAddressForm.value)"
            >
             
     
             <br>        
             <app-text-input formControlName="country" [label]='"Country"'></app-text-input>
             <app-text-input [formControl]='shippingAddressForm.controls["phone"]' [label]='"Phone Number"'></app-text-input>
             <app-text-input  formControlName="name" [label]='"Name"'></app-text-input>
             
             <app-text-input [formControl]='shippingAddressForm.controls["email"]' [label]='"Email"'></app-text-input>
             <app-text-input [formControl]='shippingAddressForm.controls["address"]' [label]='"Address"'></app-text-input>
            
      
             <div class="row">
              <div class="col-sm-4">
              <label for="state">State</label>
              </div> 
              <select class="custom-select form-group" 
              style="width: auto" 
              formControlName="state" 
              [class.is-invalid]='shippingAddressForm.get("state").errors
              && shippingAddressForm.get("state").touched'
              
             >
                <option  *ngFor='let state of selectedState?.data.data' [value]="state.id"> {{state.state}}</option>
              </select>
              </div>
    
              <div class="row">
                  <div class="col-sm-4">
                  <label for="city">City</label>
                  </div> 
                  <select class="custom-select form-group" 
                  style="width: auto" 
                  formControlName="city" 
                  [class.is-invalid]='shippingAddressForm.get("city").errors
                  && shippingAddressForm.get("city").touched'
                  
                 >
                    <option  *ngFor='let city of selectedCity?.data.data' [value]="city"> {{city}}</option>
                  </select>
                  </div>
               
                  </form>
                </div>

                </div>
              </div>
        

这是TS组件代码

loadShippingAddress() {
    this.shippingaddressService.getShippingAddress().subscribe(address => {
      console.log('address data',address);
      this.shippingAddress = address;
     if(this.shippingAddress) {
       console.log('if address',address);
       
         for (let item of this.shippingAddress.data)   
      this.shippingAddressForm.patchValue(item);
     }
    }, error => {
      console.log(error);
    })

} 这是控制台日志中的数据,显示数据库中的所有送货地址

这是申请中的结果

here i am considering that your form has only following fields 
country,phone

此处在 init 中刚刚声明了表单结构,并在 loadShippingAddress() 中添加了创建表单的实际逻辑

yourForm : FormGroup;

ngOnInit()
{
    this.yourForm = new FormGoup({
        ‘addressess’: new FormArray([]) 
    })
}

loadShippingAddress() {
     let addressess = new FormArray([]);
    
    this.shippingaddressService.getShippingAddress().subscribe(address => 
    {
         this.shippingAddress = address;
         if(this.shippingAddress) 
         {
             
                   for(let address of this.shippingAddress.data)
                   {
                          addressess.push(
                            new FormGroup({
                              'country':new FormControl(address.country),
                              'phone':new FormControl(address.phone)
                            })
                          )
                   }
        
         }
         
         
         this.yourForm = new FormGoup({
            'addressess' :  addressess
         })
         
    }, error => 
    {
        console.log(error);
    })
    
}

//getter used in html to loop through address
get adddressControls(){
    
     return (<FormArray>this.yourForm.get('addressess')).controls
}


html

<form [formGroup]='yourForm'>
<div class="row">
        <div class="col-xs-12" formArrayName="addressess">
          <div
          style="margin:5px;"
          class="row"
          *ngFor="let address of adddressControls;let i = index"
          [formGroupName]="i"
          >
            <div class="col-xs-8">
             <app-text-input formControlName="country" [label]='"Country"'></app-text-input>
            </div>
            <div class="col-xs-2">
              <app-text-input formControlName="phone" [label]='"Phone Number"'></app-text-input>
            </div>
          </div>
          <hr>
        </div>
 </div>
 </form>

注意:这是另一种使用表单而不是 formArray 的方法。这只是一次“练习”。我个人更喜欢使用 FormArray。

假设您有一项服务 return 一组“船舶”

[{
   prop1:"prop1",
   prop2:"prop2"
 },
 {
   prop1:"another1",
   prop2:"another2"
 }]

你有一个组件

  <form [formGroup]="form">
     <input formControlName="prop1">
     <input formControlName="prop2">
  </form>

您使用 @Input 和 setter 创建表单

  form:FormGroup;
  @Input() set data(value){
    this.form=new FormGroup({
       prop1:new FormControl(value.prop1),
       prop2:new FormControl(value.prop2)
    })
  }

你的父组件可以像

<div *ngFor="let ship of ships">
  <ship [data]="ship"></ship>
</div>
<button (click)="submit()">submit</button>

要获取“飞船”的值,我们可以使用 ViewChildren 并在 ngOnInit 中从服务获取数据

  @ViewChildren(ShipComponent) forms:QueryList<ShipComponent>
  constructor(private dataService:DataService){}
  ships:any[]
  result:any[]
  ngOnInit(){
     this.dataService.getData().subscribe(res=>{
       this.ships=res
     })
  }
  submit(){
    this.result=this.forms.map(x=>x.form.value)
  }

如果我们想从父级添加“新船”,我们创建一个函数

  add(){
     this.ships=[...this.forms.map(x=>x.form.value),
                     {prop1:null,prop2:null}]
  }

如果我们想删除“ships”有点复杂,我们需要传递ship的“index”并使用输出方式

在 ship 组件中,添加一个 Input index 和 output remove

@Input() index;
@Output() remove:EventEmitter<number>=new EventEmitter<number>()

并在.html

 <button (click)="remove.emit(index)">remove</button>

在父级中我们更改 .html

<div *ngFor="let ship of ships;let i=index">
  <ship [data]="ship" [index]="i" (remove)="remove($event)"></ship>
</div>

并添加一个函数删除

  remove(index:number)
  {
    this.ships.splice(index,1)
  }

stackblitz