为啥在我的反应形式中此 FormArray 更改后,我从 JSON 文件中检索对象时收到此错误消息?

Posted

技术标签:

【中文标题】为啥在我的反应形式中此 FormArray 更改后,我从 JSON 文件中检索对象时收到此错误消息?【英文标题】:Why am I obtaining this error message retrieving objects from a JSON file after this FormArray changes in my reactive form?为什么在我的反应形式中此 FormArray 更改后,我从 JSON 文件中检索对象时收到此错误消息? 【发布时间】:2020-12-18 02:19:22 【问题描述】:

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

基本上成一个表单定义我的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 代码中添加了这两种方法,用于将用户插入的值插入到此 FormArray 的多个 Commessa 字段中对象:

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);

正如您在前面的代码 sn-p 到我的 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 文件中检索并返回订单。

问题是调用 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"
,

可能是错误的,或者问题出在其他地方。

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

【问题讨论】:

检查here .then(res =&gt; &lt;Order[]&gt;res.data)你尝试将整个json文件转换为Order array类型,尝试不使用&lt;Order[]&gt; 【参考方案1】:

您在 html 中缺少 formArrayName div。

确保用 formArrayName="commessaList"

括住 HTML
<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>

【讨论】:

【参考方案2】:

你忘记使用吸气剂了吗?

get comessaList()

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

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

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

【讨论】:

以上是关于为啥在我的反应形式中此 FormArray 更改后,我从 JSON 文件中检索对象时收到此错误消息?的主要内容,如果未能解决你的问题,请参考以下文章

以反应形式设置 Angular 2 FormArray 值?

Angular 强类型反应形式

设置初始值Angular 2反应formarray

Mat Table 中的嵌套反应表单找不到控件

RStudio安装后,打开显示如下窗口,点击file等都没反应,不知为啥?请问怎么解决啊?

FormArray 字段的角度自定义验证(反应式表单)