为什么表单控件以反应形式显示 [Object][Object]?

why form control is showing [Object][Object] in reactive form?

我有 functions 可以动态创建 reactive 表单。我只需要通过 array of feilds.

这是我的 service

中的函数
createForm(fieldsArr: any[]) {
  let formObject = {};
  fieldsArr.forEach(f => {
    if(f.isArray){
      if(f.defaultValue === null){
          formObject[f.name] = this.fb.array([]);
      } else {
          formObject[f.name] = this.fb.array([this.createArrayType(f.nestedFieldsArr)]);
        }
      } else {
          formObject[f.name] = [f.defaultValue ? f.defaultValue : '', f.isRequired ? Validators.required : Validators.nullValidator];
    }
  })
  return this.fb.group(formObject);
}


createArrayType(nestedFieldsArr: any[]) {
   let nestedFormObj = {};
   nestedFieldsArr.forEach(f => {
    nestedFormObj[f.name] = [[{ value: f.defaultValue ? f.defaultValue : '', disabled: f.isDisabled ? true : false }], f.isRequired ? Validators.required : Validators.nullValidator]
   })
   let form = this.fb.group(nestedFormObj);
   return form;
}

这是 fieldsarray,我将其传递给 function 以创建 reactive-form

public marketPlaceFormFields = [
{
  name: 'pickupLocations',
  isRequired: true,
  isArray: true,
  nestedFieldsArr: [
    {
      name: 'location',
      isRequired: true
    },
    {
      name: 'lat',
      isRequired: false
    },
    {
      name: 'long',
      isRequired: false
    },
    {
      name: 'locationCode',
      isRequired: false,
    },
    {
      name: 'dateTime',
      isRequired: true
    }
  ]
},
{
  name: 'deliveryLocations',
  isRequired: true,
  isArray: true,
  nestedFieldsArr: [
    {
      name: 'location',
      isRequired: true
    },
    {
      name: 'lat',
      isRequired: false
    },
    {
      name: 'long',
      isRequired: false
    },
    {
      name: 'locationCode',
      isRequired: false
    },
    {
      name: 'dateTime',
      isRequired: true
    }
  ]
},
{
  name: 'waypoints',
  isRequired: true,
  isArray: true,
  defaultValue: null,
  nestedFieldsArr: [
    {
      name: 'location',
      isRequired: true
    },
    {
      name: 'lat',
      isRequired: false
    },
    {
      name: 'long',
      isRequired: false
    },
    {
      name: 'locationCode',
      isRequired: false
    },
    {
      name: 'type',
      isRequired: false
    },
    {
      name: 'dateTime',
      isRequired: true
    }
  ]
},
{
  name: 'bidVehicles',
  isRequired: true,
  isArray: true,
  nestedFieldsArr: [
    {
      name: 'vehicleLoadId',
      isRequired: false,
      defaultValue: 0
    },
    {
      name: 'categoryId',
      isRequired: true
    },
    {
      name: 'numberOfVehicles',
      isRequired: true
    },
    {
      name: 'loadRequirementId',
      isRequired: false,
      defaultValue: 1
    }
  ]
},
{
  name: 'shipmentWeight',
  isRequired: true
},
{
  name: 'budgetMin',
  isRequired: true
},
{
  name: 'budgetMax',
  isRequired: true
},
{
  name: 'paymentTerm',
  isRequired: false,
  defaultValue: 'Cash on Delivery'
},
{
  name: 'bidDateFrom',
  isRequired: true
},
{
  name: 'bidDateTo',
  isRequired: true
},
{
  name: 'orderId',
  isRequired: false
},
{
  name: 'insertedBy',
  isRequired: false
},
{
  name: 'shipperId',
  isRequired: false
}
];

component.ts

get pickLocatons() { return this.frm.pickupLocations as FormArray; }

ngOnInit(){
   this.marketForm = this.us.createForm(this.constants.marketPlaceFormFields);
}

component.html

<ng-container *ngFor="let pickControl of pickLocatons.controls; let i = index">
<div class="row" [formGroup]="pickControl">
  <div class="col-md-3">
     <div class="form-group">
        <label>
        Pick up Location
        <span class="text-danger font-bold ml-1">*</span>
        <i class="fa fa-info-circle ml-1 color-primary cursor-pointer" placement="auto"
           ngbPopover="{{constants.popovers.bid.pickup}}" popoverClass="op-popover"></i>
        </label>
        <div class="input-group">
           <input type="text" class="form-control" placeholder="Bazar Kharadan, Koh..." formControlName="location" [ngClass]="{'is-invalid' :  pickControl.get('location')?.errors &&
              (pickControl.get('location').touched ||  pickControl.get('location').dirty)}" />
           <div class="input-group-append cursor-pointer" (click)="openMapModal('pickupLoc', i)">
              <span class="input-group-text"><i class="fa fa-map-marker px-1"></i></span>
           </div>
        </div>
        <span class="help-block" *ngIf="pickControl.get('location')?.errors &&
           (pickControl.get('location').touched || pickControl.get('location').dirty)">
        <span *ngIf="pickControl.get('location')?.errors?.required" class="text-danger">
        {{constants.errors.required.location}}
        </span>
        </span>
     </div>
  </div>
  <div class="col-md-3">
     <div class="form-group">
        <label>
           <!-- <i class="fa fa-map-marker color-primary" aria-hidden="true"></i> -->
           Add Corresponding Code
           <i class="fa fa-info-circle ml-1 color-primary cursor-pointer" placement="auto"
              ngbPopover="{{constants.popovers.bid.code}}" popoverClass="op-popover"></i>
        </label>
        <input type="text" class="form-control" placeholder="Code" formControlName="locationCode" />
     </div>
  </div>
  <div class="col-md-3">
     <div class="form-group">
        <label>
           <!-- <i class="fa fa-calendar-o color-primary" aria-hidden="true"></i>  -->
           Date/Time
           <span class="text-danger font-bold ml-1">*</span>
           <i class="fa fa-info-circle ml-1 color-primary cursor-pointer" placement="auto"
              ngbPopover="{{constants.popovers.bid.picDate}}" popoverClass="op-popover"></i>
        </label>
        <input type="datetime-local" class="form-control" formControlName="dateTime" min="{{ (minDate | date: 'yyyy-MM-dd') + 'T00:00' }}" [max]="eConfig.DATETIME_MAX" [ngClass]="{'is-invalid' :  pickControl.get('dateTime')?.errors &&
        (pickControl.get('dateTime').touched ||  pickControl.get('dateTime').dirty)}">
        <span class="help-block" *ngIf="pickControl.get('dateTime')?.errors &&
           (pickControl.get('dateTime').touched || pickControl.get('dateTime').dirty)">
        <span *ngIf="pickControl.get('dateTime')?.errors?.required" class="text-danger">
        This is required
        </span>
        </span>
     </div>
  </div>
  <div class="col-md-3">
     <div class="form-group">
        <button class="btn btn-primary rounded-0 mt-28" (click)="addLocation()" *ngIf="i === 0">+ Add Stop</button>
        <button class="btn btn-primary rounded-0 mt-28" (click)="removeLocation(i)" *ngIf="i > 0">+ Remove</button>
     </div>
  </div>

但问题是当页面加载时,表单数组字段显示 [object][object] 作为输入的值

我不知道为什么表单域在页面加载后显示 [object][object]

注意:我只在 post.

中包含了必要的代码

据我了解,您有一个 FormGroup,其中包含一个 FormArray,其中包含一个包含 1 个 FormGroup 的列表,其中包含您的 FormControl。在 HTML 中,您需要一个 FormGroup,其中包含一个 FormArray,其中包含一个 FormControl 列表。所以看起来你嵌套太多了,或者在 HTML 中没有足够的 decaplusated。从您的评论来看,您似乎需要 FormArray,因此这是一个更新的解决方案:

createForm(fieldsArr: any[]) {
  const formGroup = new FormGroup({});
  fieldsArr.forEach(f => {
    if(f.isArray){
      if(f.defaultValue === null){
          // seems to never happen ? because you would need 1 default value for each element of your array, not just one defaultValue.
          // formObject[f.name] = this.fb.array([]);
      } else {
          formGroup.addControl(f.name, this.createNestedFormArray(f.nestedFieldsArr)); // removed the FormArray layer
      }
    } else {
      const formControl = new FormControl(f.defaultValue ? f.defaultValue : '',
                                              f.isRequired ? Validators.required : Validators.nullValidator);
      formGroup.addControl(f.name, formControl);
      // formObject[f.name] = [f.defaultValue ? f.defaultValue : '', f.isRequired ? Validators.required : Validators.nullValidator];
    }
  });
  return formGroup;
}


createNestedFormArray(nestedFieldsArr: any[]) {
   const nestedFormGroup = new FormGroup({});
   nestedFieldsArr.forEach(f => {
     const formControl = new FormControl(f.defaultValue ? f.defaultValue : '',
                                              f.isRequired ? Validators.required : Validators.nullValidator);
     if ( f.isDisabled ) {
       formControl.disable();  // moved disabled logic from constructor (not valid)
     }
     nestedFormGroup.addControl(f.name, formControl);
     // nestedFormObj[f.name] = [[{ value: f.defaultValue ? f.defaultValue : '', disabled: f.isDisabled ? true : false }], f.isRequired ? Validators.required : Validators.nullValidator]
   })
   return new FormArray([nestedFormGroup]);
}

并且在 HTML 中循环 FormArray:

<ng-container *ngFor="let pickArray of pickLocatons.controls">
  <!-- pickArray is the FormArray, containing multiple FormGroups -->
  <ng-container *ngFor="let pickNestedGroup of pickArray; let i = index" [formGroupName]="i">
    <!-- pickNestedGroup is the FormGroup, containing multiple FormControls (location, lat, long...) -->
    <!-- [formGroupName]="i" means you are using the ith element of the FormArray as reference for every following formControlNames, instead of the parent one -->
    <input formControlName="location"/>