Ошибка 7 и формы массива не может найти элемент управления с путем - PullRequest
0 голосов
/ 19 марта 2019

Я создаю группу форм с массивом внутри нее, используя mat-table источник данных.

Я начал с создания таблицы:

<form *ngIf="formGroup" [formGroup]="formGroup">
  <table mat-table [dataSource]="dataSource" *ngIf="total>0" formArrayName="distribution">
    <ng-container matColumnDef="ind_id">
      <th mat-header-cell *matHeaderCellDef> ID </th>
      <td mat-cell *matCellDef="let element">{{element.individual_id}}</td>

    </ng-container>
    <ng-container matColumnDef="ind_name">
      <th mat-header-cell *matHeaderCellDef> Name </th>
      <td mat-cell *matCellDef="let element">{{element.ind_name}}</td>

    </ng-container>
    <ng-container matColumnDef="ind_status">
      <th mat-header-cell *matHeaderCellDef> Ind. Status </th>
      <td mat-cell *matCellDef="let element">{{element.ind_status}}</td>

    </ng-container>
    <ng-container matColumnDef="project_kit">
      <th mat-header-cell *matHeaderCellDef> Kits </th>
      <td mat-cell *matCellDef="let element; let i=index;">
        <div [formGroupName]="i">
          <mat-form-field color="warn" appearance="fill">
            <mat-label>Kits</mat-label>
            <mat-select formControlName="kit" id="kit" placeholder="Kit">
              <mat-option *ngFor="let pk of projectKit" [value]="pk.project_kit">{{pk.kit_name}} part of project
                {{pk.project_name}}</mat-option>
            </mat-select>
          </mat-form-field>&nbsp;
        </div>
      </td>

    </ng-container>
    <ng-container matColumnDef="actual_date">
      <th mat-header-cell *matHeaderCellDef> Actual Date </th>
      <td mat-cell *matCellDef="let element; let i=index;">
        <div [formGroupName]="i">
          <mat-form-field color="warn" appearance="legacy">
            <mat-label>Actual Dist. Date</mat-label>
            <input formControlName="actual_date" matInput [matDatepicker]="picker2" placeholder="Actual Date">
            <mat-datepicker-toggle matSuffix [for]="picker2"></mat-datepicker-toggle>
            <mat-datepicker #picker2></mat-datepicker>
          </mat-form-field>
        </div>
      </td>
    </ng-container>
    <ng-container matColumnDef="note">
      <th mat-header-cell *matHeaderCellDef> Note </th>
      <td mat-cell *matCellDef="let element;let i=index;">
        <div [formGroupName]="i">
          <mat-form-field color="warn" appearance="legacy">
            <mat-label>Note</mat-label>
            <input formControlName="note" matInput type="text" placeholder="Note">
          </mat-form-field>
        </div>
      </td>
    </ng-container>
    <ng-container matColumnDef="actions">
      <th mat-header-cell *matHeaderCellDef> Actions </th>
      <td mat-cell *matCellDef="let element">

        <button mat-raised-button color="warn" type="submit" color="warn" (click)="addDist(element)">
          <mat-icon>add</mat-icon> Add
        </button>
      </td>
    </ng-container>

    <tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></tr>
    <tr mat-row *matRowDef="let row; columns: displayedColumns;"
      }"></tr>

  </table>
</form>

А для машинописи:

this.formGroup = this.fb.group({
      distribution: this.fb.array([
    this.createArray()
  ])
});

И createArray ():

createArray(): FormGroup {
    return this.fb.group({
      'note': new FormControl(''),
      'kit': new FormControl(''),
      'actual_date': new FormControl('')
    });

Первая машинопись запускается, когда пользователь загружает файл:

<form [formGroup]="uploadForm" role="form">
      <input #fileInput type="file" formControlName="upload" value="Upload Excel/CSV file"
        (change)="upload($event.target.files)" accept=".xlsx, .xls, .csv" />
      <button mat-raised-button id="inputFile" color="accent" (click)="reset()">
        <mat-icon color="warn">cancel</mat-icon>Reset
      </button>
    </form>

Нет ошибки для предыдущей формы загрузки файла.

Но когда я загружаю файл, появляется ошибка для массива формы:

Ошибка: не удается найти элемент управления с путем: «распределение -> 1» в _throwError (forms.js: 1790) в setUpFormContainer (forms.js: 1772) at FormGroupDirective.push

И он указывает на:

<div [formGroupName]="i">
            <mat-form-field color="warn" appearance="fill">
              <mat-label>Kits</mat-label>
              <mat-select formControlName="kit" id="kit" placeholder="Kit">
                <mat-option *ngFor="let pk of projectKit" [value]="pk.project_kit">{{pk.kit_name}} part of project
                  {{pk.project_name}}</mat-option>
              </mat-select>
            </mat-form-field>&nbsp;
          </div>

EDIT

После добавления {{formGroup.value| JSON}} я получил это:

{"distribution": [{"note": "", "kit": "", "actual_date": ""}]}

Ответы [ 3 ]

1 голос
/ 19 марта 2019

проблема в вашем источнике данных, пусть i = index ссылается на значения источника данных, если в вашем массиве меньше элементов, чем в вашем источнике данных, ваш код сбоя

Если все ваши элементы в таблицепринадлежит к FormArray, это "просто", вы можете увидеть пример в этот стек

Есть два ключа,

один, как создать форму

myform:FormGroup=new FormGroup({
    distribution:new FormArray(ELEMENT_DATA.map(x=>{
      return new FormGroup({
      position:new FormControl(x.position),
      name:new FormControl(x.name),
      weight:new FormControl(x.weight),
      symbol:new FormControl(x.symbol),

    })}))
  });

И, как мы ссылались на элементы управления

<form *ngIf="myform" [formGroup]="myform">
  <ng-container formArrayName="distribution">
<!--see that datasource is myForm.get('distribution').controls-->
<table mat-table [dataSource]="myform.get('distribution').controls" class="mat-elevation-z8" >
<ng-container matColumnDef="position">
    <th mat-header-cell *matHeaderCellDef> No. </th>
    <!--so, "element" is a formGroup-->
    <td mat-cell *matCellDef="let element;let i=index" [formGroup]="element"> <input formControlName="position" > </td>
  </ng-container>
 ....
</table>
</ng-container>
</form>

Но у вас есть «источник данных» и форма массива, некоторые не считаются.Вы можете создать функцию для ссылки на массив

get distributionArray()
{
   return this.myForm.get('distribution') as FormArray
}

И использовать в своем тд тандеме что-то вроде

<td mat-cell *matCellDef="let element;let i=index" 
     [formGroup]="distributionArray.at(i)"> 
    <input formControlName="name" > 
</td>

}

ну, это не обязательно имеет значение длявсе, но должно быть так много элементов в массиве, как в источнике данных, например,

this.myform:FormGroup=new FormGroup({
        distribution:new FormArray(ELEMENT_DATA.map(()=>{
          //only two properties empty
          return new FormGroup({
          weight:new FormControl(),
          symbol:new FormControl(),

        })}))
      });

или использование push

this.myform:FormGroup=new FormGroup({
            distribution:new FormArray([])
});
ELEMENT_DATA.forEach(()=>{
    (this.myForm.get('distribution') as FormArray).push(this.createArray())
}
0 голосов
/ 19 марта 2019

Хорошо.это означает, что вы не добавляете достаточное количество групп форм в массив.Вы звоните создать только один раз.так что работает только первый в массиве.когда индекс переходит в 1 из 0, в Formarray нет группы форм.Как я понимаю, вы хотите создать форму группы для каждой строки.поэтому вам нужно вызывать свою функцию много раз.

this.formGroup = this.fb.group({
      distribution: this.fb.array([
    this.createArray()
  ])
});

вместо создания массива каждый раз, когда вам, вероятно, следует отправить новую группу форм в существующий формат.

написать геттер для распространения для более легкого использования.

get distribution() {
   this.formGroup.get('distribution') as FormArray;
}    

затемВы можете сделать

this.distribution.push(this.fb.group({
      'note': new FormControl(''),
      'kit': new FormControl(''),
      'actual_date': new FormControl('')
    }));

для каждой строки.Я не уверен, где вы делаете создание, но это будет идти для каждого ряда.

и оставьте formGroup равным i вместо i-1 или 0.

0 голосов
/ 19 марта 2019

Вы должны определить имя массива формы выше вашего [formGroup] начала, как это formArrayName="distribution"

...