【问题标题】:How can I handle a reactive form and fields validation in a situation where some form fields are created dynamically?在动态创建某些表单字段的情况下,如何处理反应式表单和字段验证?
【发布时间】:2020-12-17 16:19:47
【问题描述】:

我正在使用 PrimeNG 开发一个 Angular 项目,我有以下问题需要使用响应式表单来解决。

基本上在我的 HTML 中,我有一些东西可以呈现这个:

感兴趣的字段基本上是代表“项目订单 ID”的 Commessa 字段。我认为有时在英语商务语言中使用 WSS 词(工作分解结构)。

这是我目前正在使用的代码:

<div class="row">
  <div class="col-2">
    <p>Commessa</p>
  </div>
  <div class="col-10">
    <input id="commessa" class="p-invalid" aria-describedby="commessa-help" formControlName="commessa" type="text" pInputText required/>
    <i class="pi pi-plus-circle"></i>
  </div>
</div>

所以当表单在我的 TypeScript 组件代码中“提交”(它不是真正的提交)时,我有这个 orderForm 对象:

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)]],
    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, []]
});

到目前为止,我只添加了一个“Commessa”字段(因为用例预见了我的表单表示的单个订单的单个 ID 订单)。但现在情况发生了变化,我必须为一个订单处理多个 ID 订单。所以我需要 n 个“Commessa”字段。

其实我最初的想法是添加+图标:

<i class="pi pi-plus-circle"></i>

单击此图标,FE 将添加一个新字段以插入第二个、第三个、...n 字段以用于新的 ID 订单。

问题是在这种情况下如何处理我的响应式表单的验证和协调?事实上,目前我必须通过 HTML 中的 formControlName 属性静态定义将与我的 FormGroup 对象关联的字段。

目前我的具体情况是:

 <input id="commessa" class="p-invalid" aria-describedby="commessa-help" formControlName="commessa" type="text" pInputText required/>

使用 formControlName="commessa"

与以下 FormGroup 元素相关
commessa: [null, [Validators.required, Validators.minLength(5)]],

以这种方式,当用户填写前端的 Commessa 字段时,FormGroup 中的 commessa 元素会被验证并检查是否插入的值是否有效。

所以我想添加一个新的输入字段,点击 + 按钮(例如具有 id="commessa_2"formControlName="commessa_2" 但是如何通过后端处理这种情况?是否可以将带有验证器的新元素添加到我的 FormGroup 对象中?

当您不知道表单中字段的确切数量时,处理这种动态情况的好策略是什么? (在这种情况下可以动态创建某些字段时)。

我怎样才能巧妙地解决这个问题?

【问题讨论】:

标签: angular primeng angular-reactive-forms angular-forms


【解决方案1】:

Angular 为此提供了Form Array。因此,不要在表单组中创建多个字段。您可以将 commessa 字段设置为 Form Array。这允许将字段作为数组动态插入其中。

【讨论】:

  • Tnx,现在我将尝试理解文档。 Onlu 一件事:你认为有可能使用它来避免改变我感兴趣的 FormGroup 架构吗?
【解决方案2】:

使用响应式表单FormArray,我们可以实现需求。

请参考以下示例 示例代码:

app.component.ts

import { Component } from '@angular/core';
import { FormControl, FormGroup, FormArray, Validators, FormBuilder } from '@angular/forms';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  constructor(private fb: FormBuilder) { }
  orderForm = this.fb.group({
    idOrdine: [null, [Validators.required]],
    commessaList: new FormArray([
      new FormControl('', [Validators.required, Validators.minLength(5)])
    ])
  });

  get commessaList(): FormArray {
    return this.orderForm.get('commessaList') as FormArray;
  }
  onFormSubmit(): void {
    for (let i = 0; i < this.commessaList.length; i++) {
      console.log(this.commessaList.at(i).value);
    }
  }
  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);
  }
}

app.component.html

<div class="container">
  <br>
  <form [formGroup]="orderForm" (ngSubmit)="onFormSubmit()">
    <div class="form-group row">
      <label for="idOrdine" class="col-sm-2 col-form-label">Id Ordine</label>
      <div class="col-sm-10">
        <input type="text" formControlName="idOrdine"
          [ngClass]="{'error':orderForm.controls.idOrdine.invalid && orderForm.controls.idOrdine.touched}"
          class="form-control" id="idOrdine">
      </div>
    </div>
    <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">
            <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>
    </div>
    <div>
      <button type="submit" class="btn btn-primary" [disabled]="orderForm.invalid">Save</button>
    </div>
  </form>
</div>

app.component.css

.container {
    margin: 100px;
}
.error{
    background-color: red;
    color:#FFF;
  }

  .row {
    display: flex;
    align-items: baseline;
    justify-content: center;
}

【讨论】:

    猜你喜欢
    • 2011-08-06
    • 2011-11-14
    • 1970-01-01
    • 2018-12-09
    • 1970-01-01
    • 1970-01-01
    • 2014-02-22
    • 2018-06-05
    • 1970-01-01
    相关资源
    最近更新 更多