为什么在我的反应形式中的 FormArray 发生变化后,我会收到此错误消息,从 JSON 文件中检索对象?

Why am I obtaining this error message retrieving objects from a JSON file after this FormArray changes in my reactive form?

我正在做一个 Angular 项目,使用反应形式并引入 FormArray(因为我有一个字段被动态创建为多个字段的情况)我是面临以下问题。

基本上是一个定义我的 HTML 代码的表格我有这样的东西:

<div class="col-10">
    <ng-container *ngFor="let commessa of commessaList.controls; index as idx">
    <div class="row">
    <div class="col-sm-8">
      <input type="text" [ngClass]="{'error':commessa.invalid && commessa.touched}"
                 [formControlName]="idx"
                 class="form-control" id="commessa">
    </div>

    <div class="col-sm-2">
      <button type="button" *ngIf="idx===0" (click)="addCommessaField()" class="btn btn-success"
        [ngClass]="'pad'"><i class="fa fa-plus-circle" aria-hidden="true"></i></button>

      <button (click)="deleteCommessaField(idx)" *ngIf="idx!==0" class="btn btn-danger">
        <i class="fa fa-trash" aria-hidden="true"></i>
      </button>
    </div>
    </div>
    </ng-container>

    </div>
</div>

此部分用于定义我的表单的突出显示部分(我可以在其中添加多个“Commessa”字段:

然后在我的 TypeScript 代码中定义了 orderForm: FormGroup; 对象,我用它来定义表单字段和相关的验证规则,我将它设置到 ngOnInit() 方法:

ngOnInit() {

    this.orderFormValues = new OrderFormValues();

    console.log("orderFormValues VALUES: " + this.orderFormValues.statoOrdine);

    this.orderForm = this.fb.group({
    idOrdine: [null, [Validators.required]],
    dataInserimentoOrdine: [new Date(), [Validators.required]],
    statoOrdine: [null, [Validators.required, Validators.minLength(5)]],
    //commessa: [null, [Validators.required, Validators.minLength(5)]],
    commessaList: new FormArray([
    new FormControl('', [Validators.required, Validators.minLength(5)])
    ]),

    CIG: [null, [Validators.required, Validators.pattern("^[a-zA-Z0-9]{10}$")]],
    dataInizioAttivita: [null, [Validators.required]],
    dataFineAttivita: [null, [Validators.required]],
    referente: [null, [Validators.required]],
    ruoloReferente: [null, [Validators.required]],
    tipologiaDiPartecipazione: [null, [Validators.required, Validators.minLength(5)]],
    quotaPercentualeDiRTI: [null, [Validators.max(100)]],

    cliente: [null, [Validators.required]],
    vatCliente: [null, [Validators.required]],
    clienteFinale: [null, []],
    vatClienteFinale: [null, []],

    tipologiaContratto: [null, []],
    importoContratto: [null, [Validators.required]],
    linkContratto: [null, [Validators.required]],
    dataSottoscrizioneContratto: [null, [Validators.required]],

    nomeSocieta: [null, [Validators.required]],
    vatSocieta: [null, []],
    buName: [null, [Validators.required]],

    presenzaAQ: [false, [Validators.required]],
    linkIdentificativoAQ: [null, []],
    accordoQuadro: [null, []],
    residuoAccordoQuadro: [null, []],
    compagineDiAQ: [null, []]

    });



    this.ordersService.getAllOrders().then(orders => {
        this.orders = orders;
        console.log("RETRIEVED ORDERS: ", orders);
        this.loading = false;
    });

        .........................................................................................
        .........................................................................................
        .........................................................................................
}

正如您在 FormGroup 定义中看到的,与多个“Commessa”字段相关的部分以这种方式定义为 FormArray :

commessaList: new FormArray([
    new FormControl('', [Validators.required, Validators.minLength(5)])
]),

为了完整起见,我在我的 TypeScript 代码中添加了这两种方法,用于将用户插入的值插入多个 Commessa 字段中 FormArray 对象:

addCommessaField() {
    this.commessaList.push(new FormControl('', [Validators.required, Validators.minLength(5)]));
}

deleteCommessaField(index: number) {
    if (this.commessaList.length !== 1) {
        this.commessaList.removeAt(index);
    }
    console.log(this.commessaList.length);
}

正如您在我的 ngOnInit() 方法中的前一个代码片段中所见,我也在执行对 OrderService 对象的调用:

this.ordersService.getAllOrders().then(orders => {
    this.orders = orders;
    console.log("RETRIEVED ORDERS: ", orders);
    this.loading = false;
});

此调用只是检索显示在主页中的订单列表(目前模拟到 JSON 文件中),我在这里遇到一个奇怪的错误。

我的getAllOrders()服务方法的代码就是这个:

getAllOrders() {
    return this.http.get<any>('assets/json_mock/ordini.json')
    .toPromise()
    .then(res => <Order[]>res.data)
    .then(data => { return data; });
}

如您所见,它从 ordini.json 文件中检索和 return 订单。

问题是调用 getAllOrders() 服务方法它检索订单列表,但在 Chrome 控制台中我也收到此错误消息:

core.js:6228 ERROR Error: Cannot find control with name: '0'
    at _throwError (forms.js:3576)
    at setUpControl (forms.js:3398)
    at FormGroupDirective.addControl (forms.js:7679)
    at FormControlName._setUpControl (forms.js:8451)
    at FormControlName.ngOnChanges (forms.js:8368)
    at FormControlName.wrapOnChangesHook_inPreviousChangesStorage (core.js:26966)
    at callHook (core.js:4730)
    at callHooks (core.js:4690)
    at executeInitAndCheckHooks (core.js:4630)
    at selectIndexInternal (core.js:9748)

奇怪的是,它发生在我使用之前的 FormArray 实现这个多个“Commessa”字段之后(在我只有一个“Commessa”输入字段之前,我没有这个错误)。我怀疑错误可能出在我原来的 JSON 内容中,但我不明白为什么以及如何解决这个问题。

按照我的 ordini.json 文件的内容:

{
  "data": [
    {
      "id": 1,

      "referente": {
        "name": "Mario",
        "surname": "Rossi",
        "complete_name": "Mario Rossi",
        "role": "Operation Manager",
        "avatar": "mario-rossi.jpg"
      },

      "company": {
        "name": "TEST S.p.A.",
        "VAT": "IT 03318271214",

        "BU": {
          "name": "Digital Solution",
          "code": "DS"
        }
      },

      "dettaglio_ordine": {
        "data_inserimento": "08/08/2020",


        "commessa": {
          "code": "AAA0001"
        },

        "identificativo_contratto_hyperlink": "LINK-ID-CONTRATTO-TEST",
        "tipologia_contratto": "ORDINE",
        "presenza_AQ": true,
        "identificativo_AQ_hyperlink": "LINK-AQ-TEST",
        "accordo_quadro": 12,
        "importo_contratto": 122000,
        "residuo_AQ": 20000,
        "compagine_di_AQ": "COMPAGINE-DI-AQ-TEST",
        "quota_percentuale_di_RTI": 20,
        "tipologia_di_partecipazione": "GARA PUBBLICA",
        "cig": "CIG-TEST-1",
        "cliente": "CLIENTE-TEST-1",
        "vat_cliente": "VAT-CLIENTE",
        "cliente_finale": "CLIENTE-FINALE-TEST-1",
        "vat_cliente_finale": "VAT-CLIENTE-FINALE",
        "data_sottoscrizione_contratto": "8/12/2020",
        "data_inizio_attivita": "8/28/2020",
        "data_fine_attivita": "8/31/2020",
        "stato_ordine": "CHIUSO"
      }
    },

    {
      "id": 2,

      "referente": {
        "name": "Mario",
        "surname": "Rossi",
        "complete_name": "Mario Rossi",
        "role": "Operation Manager",
        "avatar": "mario-rossi.jpg"
      },

      "company": {
        "name": "Blabla S.p.A.",
        "VAT": "IT 03318271214",

        "BU": {
          "name": "Cyber Security",
          "code": "CS"
        }
      },

      "dettaglio_ordine": {
        "data_inserimento": "09/08/2020",


        "commessa": {
          "code": "AAA0002"
        },

        "identificativo_contratto_hyperlink": "LINK-ID-CONTRATTO-TEST",
        "tipologia_contratto": "ORDINE",
        "presenza_AQ": false,
        "identificativo_AQ_hyperlink": "LINK-AQ-TEST",
        "accordo_quadro": 12,
        "importo_contratto": 122000,
        "residuo_AQ": 20000,
        "compagine_di_AQ": "COMPAGINE-DI-AQ-TEST",
        "quota_percentuale_di_RTI": 20,
        "tipologia_di_partecipazione": "GARA PUBBLICA",
        "cig": "CIG-TEST-2",
        "cliente": "CLIENTE-TEST-1",
        "vat_cliente": "VAT CLIENTE TEST",
        "cliente_finale": "CLIENTE-FINALE-TEST-2",
        "vat_cliente_finale": "VAT-CLIENTE-FINALE-TEST",
        "data_sottoscrizione_contratto": "8/12/2020",
        "data_inizio_attivita": "8/28/2020",
        "data_fine_attivita": "8/31/2020",
        "stato_ordine": "CHIUSO"
      }
    },

    {
      "id": 3,

      "referente": {
        "name": "Francesco Nicola",
        "surname": "Romano",
        "complete_name": "Francesco Verdi",
        "role": "Operation Manager",
        "avatar": "francesco-romano.jpg"
      },

      "company": {
        "name": "Blabla S.p.A.",
        "VAT": "IT 03318271214",

        "BU": {
          "name": "Cyber Security",
          "code": "CS"
        }
      },

      "dettaglio_ordine": {
        "data_inserimento": "10/08/2020",


        "commessa": {
          "code": "AAA0002"
        },

        "identificativo_contratto_hyperlink": "LINK-ID-CONTRATTO-TEST",
        "tipologia_contratto": "ORDINE",
        "presenza_AQ": false,
        "identificativo_AQ_hyperlink": "LINK-AQ-TEST",
        "accordo_quadro": 12,
        "importo_contratto": 122000,
        "residuo_AQ": 20000,
        "compagine_di_AQ": "COMPAGINE-DI-AQ-TEST",
        "quota_percentuale_di_RTI": 20,
        "tipologia_di_partecipazione": "GARA PUBBLICA",
        "cig": "CIG-TEST-3",
        "cliente": "CLIENTE-TEST-3",
        "vat_cliente": "XXX123",
        "cliente_finale": "CLIENTE-FINALE-TEST-3",
        "vat_cliente_finale": "YYY321",
        "data_sottoscrizione_contratto": "8/12/2020",
        "data_inizio_attivita": "8/28/2020",
        "data_fine_attivita": "8/31/2020",
        "stato_ordine": "CHIUSO"
      }

    }
  ]
}

正如您在此 JSON 文件中定义的对象中所见,commessa 字段以这种方式定义:

"commessa": {
    "code": "AAA0002"
},

可能是错误的,也可能是其他地方的问题。

我错过了什么?为什么我收到此错误?我该如何尝试修复此错误?

您忘记使用 getter?

get comessaList()
{
   return this.orderForm .get("comessaList") as FormArray
}

为避免初始错误,您可以使用 *ngIf

<div *ngIf="orderForm" [formGroup]="orderForm">
....
</div>

您在 html 中缺少 formArrayName div。

确保将 HTML 和 formArrayName="commessaList"

括起来
<div formArrayName="commessaList">
  <div class="form-group row">
    <label for="commessa" class="col-sm-2 col-form-label">Commessa</label>
    <div class="col-sm-10">
      <ng-container *ngFor="let commessa of commessaList.controls; index as idx">
        ................
        ................
      </ng-container>
    </div>
  </div>
</div>