web-dev-qa-db-ja.com

Angular FormArray patchValueエラー:TypeError:value.forEachは関数ではありません-解決方法は?

ページは元々テンプレート駆動型フォームとして作成されていましたが、自動保存機能を追加するためにリアクティブに変換されています。

ページコンポーネントのコンストラクターで、リアクティブフォーム変数を定義します。

 this.form = fb.group({
    reviewer: '',
    position: '',
    officeName: '',
    rows: fb.array([]),
    comments1: '',
    comments2: '',
    comments3: ''
});

「行」は、この問題に関連するフィールドです。

NgInitでは、Web APIを介して、永続化されたフォームデータを取得するように要求されます。データは行の配列として取得され、各行には6つのセルの配列が含まれます。 3番目のセルはFormControlに関連付けられ、他のセルは静的テキストとしてレンダリングされます。

this.rows = summaryReportQuestion.map(summaryReportQuestionObj => {
    return {
        cells: [
            summaryReportQuestionObj.questionID,
            summaryReportQuestionObj.question,
            (summaryReportQuestionObj.columnSign == '$' ? (summaryReportQuestionObj.columnSign + ' ' + summaryReportQuestionObj.target) : summaryReportQuestionObj.target + ' ' + summaryReportQuestionObj.columnSign),
            (summaryReportQuestionObj.budget == null ? summaryReportQuestionObj.budget : (summaryReportQuestionObj.columnSign == '$' ? summaryReportQuestionObj.columnSign + ' ' + this.utilityService.formatNumberWithCommas(Math.floor(summaryReportQuestionObj.budget), false) : summaryReportQuestionObj.budget + ' ' + summaryReportQuestionObj.columnSign)),
            (summaryReportQuestionObj.average == null ? summaryReportQuestionObj.average : (summaryReportQuestionObj.columnSign == '$' ? summaryReportQuestionObj.columnSign + ' ' + this.utilityService.formatNumberWithCommas(Math.floor(summaryReportQuestionObj.average), false) : summaryReportQuestionObj.average + ' ' + summaryReportQuestionObj.columnSign)),
            (summaryReportQuestionObj.top20Percent == null ? summaryReportQuestionObj.top20Percent : (summaryReportQuestionObj.columnSign == '$' ? summaryReportQuestionObj.columnSign + ' ' + this.utilityService.formatNumberWithCommas(Math.floor(summaryReportQuestionObj.top20Percent), false) : summaryReportQuestionObj.top20Percent + ' ' + summaryReportQuestionObj.columnSign))
        ]
    };
});

let faRows = new FormArray([]);
for (var i = 0, len = this.rows.length; i < len; i++) {
    let row = this.rows[i].cells;
    for (var j = 0, length = this.rows[i].cells.length; j < length; j++) {
        let fc = new FormControl(this.rows[i].cells[j]);
        faRows.Push(fc);
    }
}

// this.form.setValue({rows: faRows});
// this.form.setControl('rows', faRows);

HTMLの場合:

<tbody>
    <tr *ngFor="let row of rows;let r = index" [attr.data-index]="r">
        <ng-container>
            <td *ngFor="let cell of row.cells;let i = index" [attr.data-index]="i">
                <span *ngIf="i != 2">{{cell}}</span>
                <!-- <input type="text" formControlName="form.rows[r]" *ngIf="i == 2"> -->
            </td>
        </ng-container>
    </tr>
</tbody>

コメントと回答に基づいて、私の意図とコードを明確にしました。 [ありがとう@amalと@DeborahK]現在、各行のデータの1つのセルのみをFormControlに結び付けており、各行の他のセルは{{cell}}で表示されています。

したがって、this.form.rowsだけでなくthis.rows(htmlに表示)のコンテンツをレンダリングする必要があります。

私は現在、これを達成する方法を理解する上で2つの問題を抱えています。 TypeScriptでは、行のFormControlsを作成するデータの行を反復するループの最後のブロックを残して、配列faRowsには、私が期待するもの、FormControlsのFormArrayが正確に含まれ、それぞれが正しい関連付けられた保存値を取得しています。しかし、this.rowsからデータをコピーしてform.rowsのFormControlsを作成しようとすると、setValueまたはsetControlのいずれかを正しく機能させることができません。これは、私の2番目の問題であるhtmlページのFormControlの命名に関連している可能性があります。

フォーム変数を参照してhtmlでformControlNameを動的に作成する方法がわかりません。これは私が想像することですが、機能しません。

 <input type="text" formControlName="form.rows[r]" *ngIf="i == 2">

Page rendered as template driven form

5
lynnjwalker

私の知る限り、FormArrayを使用して.patchValueを呼び出すことはできません。

私のフォームも同様に設定されます。ここで、タグは私のFormArrayです。

    this.productForm = this.fb.group({
        productName: ['', [Validators.required,
                           Validators.minLength(3),
                           Validators.maxLength(50)]],
        productCode: ['', Validators.required],
        starRating: ['', NumberValidators.range(1, 5)],
        tags: this.fb.array([]),
        description: ''
    });

編集用のデータを設定するとき、私はこれをしなければなりませんでした:

    this.productForm.patchValue({
        productName: this.product.productName,
        productCode: this.product.productCode,
        starRating: this.product.starRating,
        description: this.product.description
    });
    this.productForm.setControl('tags', this.fb.array(this.product.tags || []));

単純なFormControlのそれぞれにpatchValueを使用し、FormArrayにsetControlを使用しました。

あなたはそれを試してみて、それがあなたの問題を解決するかどうか見ることができます。

26
DeborahK