为什么这个 Angular 表格在我完全填写之后仍然处于无效状态?

Why this Angular form remains in invalid state after that I completly filled it?

我正在使用 PrimeNG 开发一个 Angular 应用程序,我遇到了以下表单问题。

当我填写表格时,如果满足所有验证器规则,它仍然处于无效状态。

这是我的组件HTML视图:

<p-dialog header="Inserire un nuovo asset"
          maximizable="true"
          [(visible)]="displayNewAssetDialog"
          (onHide)="closeDialog()"
          position="top"
          [style]="{width: '50vw'}">

        <form [formGroup]="newAssetForm" id="addAssetForm" (ngSubmit)=saveNewAsset()>

            <div class="row">
                <div class="col-2">
                  <p>Tipo asset</p>
                </div>
                <div class="col-10">
                  <p-dropdown id="assetType"
                              [options]="assetTypeList" 
                              [(ngModel)]="selectedAssetTypeNg" 
                              formControlName="asset_type"
                              placeholder="Tipo asset" 
                              optionLabel="type" 
                              [showClear]="true">
                  </p-dropdown>
                </div>
              </div>

              <div class="row">
                <div class="col-2">
                  <p>Modello</p>
                </div>
                <div class="col-10">
                    <input id="assetModel" formControlName="asset_model" type="text" pInputText />
                </div>
              </div>
              <!--
              <div class="row">
                <div class="col-2">
                  <p>Assegnato a</p>
                </div>
                <div class="col-10">
                  <p-dropdown id="employee_allocation"
                              [options]="employeesList$ | async" 
                              formControlName="employee_allocation"
                              placeholder="Impiegato" 
                              optionLabel="completeName" 
                              [showClear]="true">
                  </p-dropdown>
                </div>
              </div>
            -->
            

              <div class="row">
                <div class="col-2">
                  <p>Caratteristiche</p>
                </div>
                <div class="col-10">
                    <textarea id="assetFeatures" 
                              class="p-inputtextarea"
                              formControlName="asset_features" 
                              [rows]="5" [cols]="30" 
                              pInputTextarea 
                              autoResize="autoResize">
                    </textarea>
                </div>
              </div>

              <div class="row">
                <div class="col-2">
                  <p>Serial Number</p>
                </div>
                <div class="col-10">
                    <input id="serialNumber" formControlName="serial_number" type="text" pInputText />
                </div>
              </div>


              <div class="row">
                <div class="col-2">
                  <p>Data di consegna</p>
                </div>
                <div class="col-10" [ngClass]="{'ng-pristine ng-invalid ng-touched': isEmptyDate}">
                  <p-calendar [ngClass]="{'invalid-date': isValidDate}"
                              id="allocationDate" 
                              inputId="allocationDate"
                              formControlName="allocation_date"
                              >
                  </p-calendar>
                </div>
              </div>

              <div class="row">
                <div class="col-2">
                  <p>company</p>
                </div>
                <div class="col-10">
                    <input id="company" formControlName="company" type="text" pInputText />
                </div>
              </div>

              <div class="row">
                <div class="col-2">
                  <p>Note</p>
                </div>
                <div class="col-10">
                    <textarea id="notes" 
                              class="p-inputtextarea"
                              formControlName="notes" 
                              [rows]="5" [cols]="30" 
                              pInputTextarea 
                              autoResize="autoResize">
                    </textarea>
                </div>
              </div>

              <div class="row">
                <div class="col-2">
                  <p>Fattura/Provenienza</p>
                </div>
                <div class="col-10">
                    <textarea id="invoice" 
                              class="p-inputtextarea"
                              formControlName="invoice" 
                              [rows]="5" [cols]="30" 
                              pInputTextarea 
                              autoResize="autoResize">
                    </textarea>
                </div>
              </div>

              <p-footer>
                <span class="p-buttonset">
                  <button pButton 
                          type="submit"
                          label="Save" 
                          icon="pi pi-check"
                          [disabled]="!newAssetForm.valid">

                  </button>
                  <button pButton type="button" label="Cancel" icon="pi pi-times" (click)="closeDialog()"></button>
              </span>
              </p-footer>

              <p>{{newAssetForm.valid}}</p>
              <p>{{newAssetForm.status | json }}</p>
              <p>{{newAssetForm.value | json }}</p>
        </form>
</p-dialog>

如您所见,在此文件末尾,我添加了一些包含表单状态信息的段落标记,用于调试目的。您还可以看到,当表单处于无效状态时,提交按钮被禁用。

那么这是我的组件的 TypeScript 代码:

import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { Observable } from 'rxjs';
import { AssetService } from 'src/app/services/asset.service';
import { EmployeeService } from 'src/app/services/employee.service';
import { Employee } from 'src/app/shared/interfaces/employee';

@Component({
  selector: 'app-asset-add-form',
  templateUrl: './asset-add-form.component.html',
  styleUrls: ['./asset-add-form.component.scss']
})
export class AssetAddFormComponent implements OnInit {

  @Input()
  displayNewAssetDialog: boolean;

  @Output()
  onDialogClose: EventEmitter<any> = new EventEmitter(); 

  newAssetForm: FormGroup;
  
  assetTypeList: any[];
  selectedAssetTypeNg: any;
  isValidDate: boolean;
  isEmptyDate: true;
  loading: boolean = true;

  employeesList$:Observable<Employee[]>;

  constructor(private fb: FormBuilder,
              private employeeService: EmployeeService,
              private assetService: AssetService) { }

  ngOnInit(): void {
    console.log("AssetAddFormComponent INIT");

    this.assetTypeList = [
      {type: 'Notebook', code: 'NB' },
      {type: 'Notebook cliente', code: 'NB-C' },
      {type: 'Smartphone', code: 'SP' },
      {type: 'Drive', code: 'DRV' },
      {type: 'Licenza Office 2016', code: 'LO-2016' },
      {type: 'Licenza Office 2019', code: 'LO-2019' },
      {type: 'Licenza Office 2019 Professional', code: 'LO-2019-P' },
      {type: 'Licenza Office Plus 2019 Professional', code: 'LO-P-2019-P' },
      {type: 'RAM', code: 'RAM' },
      {type: 'Monitor', code: 'MON' },
      {type: 'Muletto', code: 'MUL' },
      {type: 'SIM', code: 'SIM' }
    ];

    this.loadEmployeesList().then(() => {this.loading = false;})

    this.newAssetForm = this.fb.group({
      asset_type: [null, [Validators.required]],
      asset_model: [null, [Validators.required]],
      //employee_allocation: [null],
      asset_features: [null, [Validators.required]],
      serial_number: [null, [Validators.required]],
      accessories: [null, [Validators.required]],
      allocation_date: [null, [Validators.required]],
      company: [null, [Validators.required]],
      notes: [null, [Validators.required]],
      invoice: [null, [Validators.required]]

    });
  }

  closeDialog() {
    console.log("CHILD COMPONENT closeDialog() START");
    this.onDialogClose.emit();
  }

  // Load the list of all the employees:
  async loadEmployeesList() {
    this.employeesList$ = await this.employeeService.getAllEmployees()
    console.log("employeesList$: ", this.employeesList$);
  }

  async saveNewAsset(){
    console.warn("saveNewAsset()",this.newAssetForm.value);    
    
    let parameters = {      
      firstName: this.newAssetForm.value.a,
      surname: this.newAssetForm.value.surname,      
      placeOfBirth: this.newAssetForm.value.placeOfBirth,
      socialSecurityCode: this.newAssetForm.value.socialSecurityCode,
      birthDate: this.newAssetForm.value.birthDate,
      companyEmail: this.newAssetForm.value.companyEmail,
      personalEmail: this.newAssetForm.value.personalEmail,     
      companyPhone: this.newAssetForm.value.companyPhone,  
      personalPhone: this.newAssetForm.value.personalPhone,  
      selectedEmployeeStatus: this.newAssetForm.value.selectedEmployeeStatus
    }

    if(this.newAssetForm.value.employee_allocation)
      parameters["employee_allocation"] = this.newAssetForm.value.employee_allocation;

    await this.assetService.saveAsset(parameters);
  }

}

问题是在我填写表格之后它仍然处于无效状态。这些是前面调试段落标签在页面中打印的信息:

false

"INVALID"

{ "asset_type": { "type": "Notebook", "code": "NB" }, "asset_model": "ASUS X509JA-EJ026T ", "asset_features": "test1", "serial_number": "123xxx", "accessories": null, "allocation_date": "2020-12-26T23:00:00.000Z", "company": "Technology", "notes": "test2", "invoice": "test3" }

如您所见,表格似乎已完美填写,但仍处于无效状态。

这是打印屏幕:

为什么?我错过了什么?怎么了?我该如何解决这个问题?我如何检查表格中的确切错误是什么? (我想也许使用调试器我可以看到哪些字段出错或者我可以打印出这些错误)

我看到您声明了一个名为“accessories”的表单控件,例如(accessories: [null, [Validators.required]]) 在你的表单组中是“必需的”但是你没有在你的 html 中使用它导致永久空值这是默认值你提供的。

您可以在表单中添加另一个条目,例如:

<div class="col-10">
   <input id="accessories" formControlName="accessories" type="text" pInputText />
</div>

然后尝试输入一些随机值来测试它。