web-dev-qa-db-ja.com

Angular2:FormArrayのインデックス1にフォームコントロールが見つかりません

実行時に、JSONオブジェクトからすべてのレコードを取得し、フォームコントロールで値を取得しています。ただし、form-arrayでは、多くのレコードの最初のものしか取得していません。

コンソールに表示されるエラー:

FormArray._throwIfControlMissingのインデックス1にフォームコントロールが見つかりません

JSONオブジェクトとエラーの画像:

enter image description here

  1. インターフェース
export interface IService {
    ServiceID: number,
    Name: string,
    Staffs: IStaffView[]
}

export interface IStaffView {
    StaffServiceID: number,
    StaffID: number,
    Name: string
}
  1. 成分
import { Component, OnInit, Input } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Location } from '@angular/common';
import { Observable } from 'rxjs/Rx';
import { FormBuilder, FormGroup, FormControl, FormArray , Validators } from '@angular/forms';

import { RESTService } from '../../Service/REST.service';
import { IService, IStaffView } from '../../Model/service.model';
import { DBOperation } from '../../Shared/enum';
import { Global } from '../../Shared/global';

@Component({
    selector: 'app-service-detail',
    templateUrl: 'app/Components/service-detail/service-detail.component.html'
})

export class ServiceDetailComponent implements OnInit {
   
    service: IService;
    services: IService[];
    staffview: IStaffView;
    staffsview: IStaffView[];

    serviceFrm: FormGroup;
    Staffs: FormArray;

    msg: string;
    indLoading: boolean = false;
    btnTitle: string;
    dbops: DBOperation;

    constructor(
        private fb: FormBuilder,
        private _restService: RESTService,
        private location: Location,
        private _route: ActivatedRoute
    ) {
        const id = this._route.snapshot.params['id'];
        if (!id || id == 0) {
            this.btnTitle = 'Save';
            this.dbops = DBOperation.create;
        } else {
            this.btnTitle = 'Edit';
            this.dbops = DBOperation.update
        }
    }

    ngOnInit(): void {
        //this.Staffs = this.fb.array([
        //    this.initStaff()
        //]);


        this.serviceFrm = this.fb.group({
            ServiceID: [''],
            Name: ['', Validators.required],
            Staffs: this.fb.array([
                this.initStaff()
            ])
        });

        this.getService();
    }

    initStaff() {
        return this.fb.group({
            StaffServiceID: [''],
            StaffID: [''],
            Name: ['']
        });
    }

    getService(): void {
        const id = parseInt(this._route.snapshot.params['id']);
        if (id && id > 0) {
            this.indLoading = true;
            this._restService.getById('/api/serviceapi/', id)
                .subscribe(resp => this.serviceFrm.setValue(resp)
                , error => this.msg = <any>error);
        }
    }

}
  1. HTMLコード
  <div class="row form-group">
                    <div class="col-md-3">
                        <label for="message-text" class="control-label">Staffs</label>
                    </div>
                    <div formArrayName="Staffs">
                        <div *ngFor="let staff of serviceFrm.controls.Staffs.controls; let i=index" formGroupName="{{i}}">
                            <div>
                                <label>Name</label>
                                <input type="text" class="form-control" formControlName="Name">
                            </div>
                        </div>
                    </div>
                </div>
5

上記のエラーは、this.serviceFrm.setValue(resp)https://github.com/angular/angular/blob/master/packages/forms/src/model.ts#L1382 )を呼び出すことによって発生します。 。

このメソッドは厳密なチェックを実行するため、存在しないコントロールの値を設定しようとしたり、コントロールの値を除外したりすると、エラーがスローされます。

インデックス0に初期FormGroupが1つしかないFormArrayに(スナップショットに従って)3つのアイテムの配列を割り当てようとしているため、インデックス1に値を割り当てることができません。

値にパッチを適用する前にフォーム配列を空にするには、patchValue()の代わりにsetValue()(部分的な値を受け入れる)を使用して、各値をループにプッシュします。

getService(): void {
  const id = parseInt(this._route.snapshot.params['id']);
  if (id && id > 0) {
    this.indLoading = true;
    this._restService.getById('/api/serviceapi/, id).subscribe(
      resp => {
        // get form array reference
        const staffs = this.serviceFrm.get('Staffs') as FormArray;
        // empty form array
        while (staffs.length) {
          staffs.removeAt(0);
        }
        // use patchValue instead of setValue
        this.serviceFrm.patchValue(resp);
        // add form array values in a loop
        resp.Staffs.forEach(staff => staffs.Push(this.fb.group(staff));
      }, 
      error => this.msg = <any>error
    );
  }
}
11
Andriy

FormArraysでsetControlを使用することができます。以下のコードは Deborah Kurata の例です:

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: ''
});

...

// Update the data on the form
this.productForm.patchValue({
    productName: this.product.productName,
    productCode: this.product.productCode,
    starRating: this.product.starRating,
    description: this.product.description
});

// This line makes the array update!
this.productForm.setControl('tags', this.fb.array(this.product.tags || []));
0
Francesco

これを試して:

<div class="row form-group">
                    <div class="col-md-3">
                        <label for="message-text" class="control-label">Staffs</label>
                     </div>
                    <div >
                        <div *ngFor="let staff of serviceFrm.controls.Staffs.controls; let i=index" formArrayName="Staffs">
                            <div [formGroupName]="i">
                                <label>Name</label>
                                <input type="text" class="form-control" formControlName="Name">
                            </div>
                        </div>
                    </div>
                </div>
0
Nadhir Falta