簡體   English   中英

Angular 2 Reactive Forms中FormArray內的FormGroup

[英]FormGroup inside FormArray in Angular 2 Reactive Forms

我未能讓 Angular 2 反應式表單工作,其中FormGroup嵌套在FormArray 中 有人可以告訴我我的設置有什么問題嗎?

為簡潔起見,省略了代碼中不相關的部分。

以下是我的組件

orderForm: FormGroup = this.fb.group({
    id: [''],
    store: ['', Validators.required],

    //The part related to the error
    order_lines: this.fb.array([
        this.fb.group({
           id: [''],
           order_id: [],
           product_id: [],
           description: ['', Validators.required],
           unit_price: ['', Validators.required],
           discount: [0],
           units: [1, Validators.required],
           line_total: ['', Validators.required]
        })
    ])
});

constructor(private fb: FormBuilder) {  }

//Order instance is passed from elsewhere in the code
select(order: Order): void {
    this.orderForm.reset(order)
}

傳遞給 select 方法的Order實例是這樣的:

  {
        "id": 20,
        "store": "Some Store",
        "order_lines": [
            {
                "id": 6,
                "order_id": 20,
                "product_id": 1,
                "description": "TU001: Polka dots",
                "unit_price": "1000.00",
                "discount": "100.00",
                "units": 2,
                "line_total": "1900.00"
            },
            {
                "id": 7,
                "order_id": 20,
                "product_id": 2,
                "description": "TU002: Polka dots",
                "unit_price": "500.00",
                "discount": "0.00",
                "units": 1,
                "line_total": "500.00"
            }
        ]
    }

視圖模板如下所示。

<form [formGroup]="orderForm">
   <input type="number" formControlName="id">
   <input type="text" formControlName="store">

   <div formArrayName="order_lines">
      <div *ngFor="let line of orderForm.get('order_lines'); let i=index">
          <div [formGroupName]="i">
               <input type="text" [formControlName]="product_id">
               <input type="text" [formControlName]="description">
               <input type="number" [formControlName]="units">
               <input type="number" [formControlName]="unit_price">
               <input type="number" [formControlName]="line_total">
          </div>
      </div>
   </div>
</form>

這個設置給了我一個控制台錯誤**無法在 order_lines -> 0 -> ** 找到控制。 我想知道我做錯了什么。

我可以讓它與 order_lines FormArray 中的簡單FormControl一起使用 但它無法給定的錯誤時,FormGroupFormArray內部使用。

你能幫我解決這個問題嗎?

而不是使用form.get更好地使用如下控件 -

<form [formGroup]="orderForm">
   <input type="number" formControlName="id">
   <input type="text" formControlName="store">

   <div formArrayName="order_lines">
      <div *ngFor="let line of orderForm.controls.order_lines.controls; let i=index">
          <div [formGroupName]="i">
               <input type="text" formControlName="product_id">
               <input type="text" formControlName="description">
               <input type="number" formControlName="units">
               <input type="number" formControlName="unit_price">
               <input type="number" formControlName="line_total">
          </div>
      </div>
   </div>
</form>

工作示例

你所缺少的——

  • 你缺少.control去年* ngFor的遍歷控制。
  • 如果您使用上述方法,則需要將[formControlName]替換為formControlName

@Johna,補充我的回答:

你有兩個功能

  buildForm(data:any):FormGroup
  {
    return data?this.fb.group({
      id: [data.id?data.id:''],
      store: [data.store?data.store:'', Validators.required],
      order_lines:this.fb.array(this.buildArrayControl(data.order_lines?data.order_lines:null))
    })
    :
    this.fb.group({
      id: [''],
      store: ['', Validators.required],
      order_lines:this.fb.array(this.buildArrayControl(null))
    })

  }

  buildArrayControl(data:any[]|null):FormGroup[]
  {
    return data?
    data.map(x=>{
      return this.fb.group({
           id: [x.id?x.id:''],
           order_id: [x.order_id?x.order_id:''],
           product_id: [x.product_id?x.product_id:''],
           description: [x.description?x.description:'', Validators.required],
           unit_price: [x.unit_price?x.unit_price:'', Validators.required],
           discount: [x.discount?x.discount:0],
           units: [x.units?x.units:1, Validators.required],
           line_total: [x.line_total?x.line_total:'', Validators.required]
        }) 
    })
    :
    [this.fb.group({
           id: [''],
           order_id: [],
           product_id: [],
           description: ['', Validators.required],
           unit_price: ['', Validators.required],
           discount: [0],
           units: [1, Validators.required],
           line_total: ['', Validators.required]
        }) 
    ]
  }

然后你可以做,例如

this.orderForm = this.buildForm(
    {
      id:'112',
      store:'22655',
      order_lines:[{description:1222,....},{description:1455,...}]
    }
  )

 //or 
 this.orderForm=this.buildForm(null);

您可以使用 *ngFor 內聯移動 formArrayName 並在 ngFor 中包含 .controls,因為我們正在循環表單控件。

<div>
      <div formArrayName="order_lines" *ngFor="let line of orderForm.get('order_lines').controls; let i=index">
          <div [formGroupName]="i">
               <input type="text" [formControlName]="product_id">
               <input type="text" [formControlName]="description">
               <input type="number" [formControlName]="units">
               <input type="number" [formControlName]="unit_price">
               <input type="number" [formControlName]="line_total">
          </div>
      </div>
   </div>

我知道 OP 的問題已經得到解答,但我想發布我的問題的解決方案,由於 OP 的問題和以上答案,我解決了這個問題。

我被要求創建一個動態表單(問卷),但在實現嵌套的 Angular 動態表單時遇到了一些問題。

生成的動態表單可以預先填充多個條目,或者您可以向空列表中添加更多字段,或兩者兼而有之。

我的用例創建了一個汽車檢查表,起始數組上的每個項目都是操作員的“待辦事項”任務。

Angular 9 + Material + Bootstrap。

以下代碼將更好地闡明:

 /* Component Typescript */ constructor( private formBuilder: FormBuilder ) { } arrayTitoli = [ "TASK1", "TASK2", "TASK3", "TASK4", "TASK5", ] addTaskField(value) { this.array.push( this.formBuilder.group({ titolo: value, checkbox: false, noteAggiuntive: "" }) ) } get titoliArray(){ let array = []; for(let i = 0;i <this.arrayTitoli.length;i++){ array.push( this.formBuilder.group({ titolo: this.arrayTitoli[i], checkbox: false, noteAggiuntive: "" }) ) } return array; } angForm: FormGroup = this.formBuilder.group({ array: this.formBuilder.array(this.titoliArray) }); get array(): FormArray { return this.angForm.get('array') as FormArray; } onFormSubmit(): void { console.log(this.angForm.value) }
 <!-- Component HTML --> <div class="p-2"> <form [formGroup] = "angForm" (ngSubmit)="onFormSubmit()"> <div> <button type="submit" class="btn btn-primary">Send</button> </div> <div formArrayName="array"> <div *ngFor="let line of array.controls; index as idx;"> <div [formGroupName]="idx"> <mat-grid-list style="text-align: center!important;" [cols]="3" rowHeight="13vh" (window:resize)="onResize($event)"> <mat-grid-tile style="font-weight: bold;font-size: smaller;" class="col-md-4 col-xs-4" colspan="1"> {{line.controls['titolo'].value}} </mat-grid-tile> <mat-grid-tile class="col-md-4" colspan="1"> <mat-checkbox formControlName="checkbox" #check color="primary"> <!--<button *ngIf="!mobile" type="button" (click)="check.toggle()" class="btn btn-{{check.checked ? 'success' : 'danger'}} btn-sm" >SPUNTA</button>--> </mat-checkbox> <mat-form-field [style.maxWidth.%]="mobile ? '70' : '100'" style="margin-left: 10%;"> <mat-label *ngIf="!mobile">Note aggiuntive</mat-label> <mat-label *ngIf="mobile">Note</mat-label> <textarea formControlName="noteAggiuntive" matInput value='' cdkTextareaAutosize #autosize="cdkTextareaAutosize" cdkAutosizeMinRows="1" cdkAutosizeMaxRows="5"></textarea> </mat-form-field> </mat-grid-tile> </mat-grid-list> <hr> </div> </div> </div> </form> <div> <mat-form-field> <input type="text" #newTask matInput> </mat-form-field> <span class="px-2"> <button type="button" class="btn btn-primary" (click)="addTaskField(newTask.value)">Create</button> </span> </div> </div>

希望它可以有用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM