0

I have a form with next format:

  this.form = this.formBuilder.group({
      title: new FormControl('', [Validators.required, Validators.maxLength(25)]),
      description: new FormControl('', [Validators.maxLength(45)]),
      event: new FormControl('', [Validators.required]),
      properties: this.formBuilder.array([])
    });

Properties array is dynamic and values always depend on selected event. This array can have at least 3 values and max 50 values. Each event has an unique name. That's why I fill this array after event has been selected with the next way:

 getValuesOfPoperty = function (prop) {
    this.selectedEventProperties = [];
    this.propertyService.getValuesOfPoperty(prop.propertyId)
      .subscribe(res => {
        this.selectedEventProperties.push({
          required: prop.required,
          name: prop.name,
          value: prop.defaultValue,
          type: res.name,
          items: res.items
        });
      })

  };

createItem(prop): FormGroup {
    return this.formBuilder.group({
      [prop.name]: prop.value
    });
  }

selectedEvent(type) {
   const temp = this.form.get('properties') as FormArray;

   type.properties.forEach(item => {
     temp.push(this.createItem(item));
     this.getValuesOfPoperty(item)
   });

   console.log(this.form.value)
 }

Console shows me appropriate form object with correct nested properties array like this:

{
 title: '',
 description: '',
 event: 'auth',
 properties: [{ Date: null},
              { Login: null},
              { Result: null}]
}

But at the meantime I get an error in console about every nested object:

Cannot find control with path: 'properties -> Date'

Cannot find control with path: 'properties -> Login'

Cannot find control with path: 'properties -> Result'

This is my HTML

  <form [formGroup]="form" novalidate autocomplete="off">

  <mat-form-field class="form-full-width">
                <mat-select placeholder="event"
                            required
                            formControlName="event">
                  <mat-option *ngFor="let type of events"
                              (click)="selectedEvent(type)"
                              [value]="type.name">
                    {{ type.name }}
                  </mat-option>
                </mat-select>
              </mat-form-field>

              <mat-form-field class="form-full-width">
                <input matInput
                       required
                       formControlName="title"
                       placeholder="title">
              </mat-form-field>

              <mat-form-field class="form-full-width">
                <input matInput
                       formControlName="description"
                       placeholder="description">
              </mat-form-field>

              <div *ngFor="let prop of selectedEventProperties" formArrayName="properties">

                <!-- SELECTS -->
                <mat-form-field class="form-full-width">
                  <mat-select required="{{prop.required}}"
                              formControlName="{{prop.name}}"
                              placeholder="{{prop.name}}">
                    <mat-option *ngFor="let item of prop.items"
                                [value]="prop.value">
                      {{ item.value }}
                    </mat-option>
                  </mat-select>
                </mat-form-field>
              </div>

</form

I appreciate if somebody could help me to figure out where my mistake is or could tell me what I'm doing wrong

Thanks in advance.

antonyboom
  • 1,161
  • 2
  • 17
  • 44

1 Answers1

1

So the problem was in creation dynamic array to display selected event properties, cause I used service, html rendered before the actual data has been received, this is how I solved this problem

 getValuesOfPoperty = function (prop, temp) {
    this.selectedEventProperties = [];
    this.propertyService.getValuesOfPoperty(prop.propertyId)
      .subscribe(res => {
        // add property to dynamic array when the data has been received
        temp.push(this.createItem(prop));
        // work with an array for event properties
        this.selectedEventProperties.push({
          required: prop.required,
          name: prop.name,
          value: prop.defaultValue,
          type: res.name,
          items: res.items
        });
      })

  };

createItem(prop): FormGroup {
    return this.formBuilder.group({
      [prop.name]: prop.value
    });
  }

selectedEvent(type) {
   const temp = this.form.get('properties') as FormArray;

   type.properties.forEach(item => {
     this.getValuesOfPoperty(item, temp)
   });

   console.log(this.form.value)
 }
antonyboom
  • 1,161
  • 2
  • 17
  • 44