web-dev-qa-db-ja.com

`FormGroup`の入力フィールドに事前入力-Angular2

私はAngular2-ReactiveFormsを使用しています。フォームのフィールドの1つに事前入力された値を表示するまで、すべて正常に機能します。

シナリオ:ページには複数のボタンがあり、各ボタンは次のようなフィールドを持つフォームを開きます

  1. 名前
  2. Eメール
  3. メッセージ
  4. 製品コード->この値は、サービスからのアイテムコードに従って事前入力されます。

失敗するシナリオ:製品コードの入力値がnullになります。

TSコード:

import { FormGroup, FormBuilder, Validators } from '@angular/forms';
queryForm: FormGroup;
constructor(private _productService: ProductService, fb: FormBuilder) {
    this.queryForm = fb.group({
        'name': [null, Validators.compose([Validators.required, Validators.minLength(5)])],
        'email': [
            null, [Validators.required, Validators.email]
        ],
        'message': [null,Validators.compose([Validators.required, Validators.minLength(5)])],
        'pcode': [
            null
        ],
    })
}

HTMLフォーム:

<div *ngFor="let item of product">
<form action="#" [formGroup]="queryForm" 
 (ngSubmit)="submitForm(queryForm.value)" method="post" 
  novalidate="" class="text-left note" id="f_{{item.productId}}">
    [ .... rest of the fields ...]
    <div class="form-group hidden">
          <input type="hidden " class="form-control " id="pcode " name="pcode" 
        formControlName="pcode" [value]="item.productCode" />
     </div>
     <div class="form-group">
           <button type="submit" class="btn1" [disabled]="!queryForm.valid">Submit</button>
      </div>
</form>
</div>

どうすればこれを達成できますか?

6
Gags

UPDATE:わかったように、単一のformArrayではなくformControlが必要です。したがって、フォームを作成するときに次のように宣言します。

this.queryForm = this.fb.group({
  arrayOfData: this.fb.array([]) // name a proper name to array
})

データを受信したら、setValueまたはpatchValueを使用できます。ここで、応答を繰り返し、値をフォーム配列にパッチします。コールバックでpatchValues-メソッドを呼び出します(サブスクライブ)。

patchValues() {
  const control = <FormArray>this.queryForm.controls.arrayOfData;
  this.items.forEach(x => {
    control.Push(this.patchValue(x.first_name, x.pcode))
  })
}

patchValue(name, code) {
  return this.fb.group({
    name: [name],
    pcode: [code]
  })    
}

テンプレートでformarrayを繰り返し、formgroupname(インデックス)を設定することも忘れないでください。

<div formArrayName="arrayOfData">
  <div *ngFor="let code of queryForm.controls.arrayOfData.controls; let i = index">
    <div formGroupName="{{i}}">
      <label>Name: </label>
      <input formControlName="name" /><br>
      <label>Product Code: </label>
      <input formControlName="pcode" /><br>
    </div>
  </div>
</div>

デモ


元の回答:

テンプレートではなく、常にコンポーネントにフォーム値を設定する必要があります。サービスから値を受け取ったときにpatchValueまたはsetValueを使用できます...したがって、コールバック内でこれを行うことができます(サブスクライブ):

this.myService.getSomeData()
  .subscribe(data => {
     this.item = data;
     this.queryForm.patchValue({pcode: this.item.productCode})
  });

その場合、フォームで[value]="item.productCode"を使用する必要はありません。代わりに、この値はフォームコントロールで設定されます。

デモ

7
AJT82