Angular ReactiveForms FormArray removeAt удаляет все элементы в FormArray - PullRequest
1 голос
/ 08 мая 2019

Я создаю форму, состоящую из двух FormArray s, items и savedItems.На каждом элементе массива формы есть кнопка, которая может удалить этот элемент из массива.

Верх / первый FormArray заполняется из списка объектов.В то время как второй FormArray предназначен для заполнения пользователем.

Проблема в том, что при первом FormArray всякий раз, когда я нажимаю кнопку «Удалить запись», все элементы в FormArray удаляются вместоэлемент, принадлежащий (в той же позиции) кнопке «Удалить запись».

Вот мое определение формы:

<form [formGroup]="boxForm" (ngSubmit)="onSubmit(boxForm)">
<div class="row" formArrayName="savedItems" *ngFor="let item of getSavedItems.controls; let i = index;"  >
  <div *ngFor="let trailer of trailerModelList; let x = index;" >
    <div class="form-group" [formGroupName]="i" style="margin-bottom: 10px">
      <div>
        <div class="col-sm-5 form-group">
          <label for="name">Origin</label>
          <input class="form-control" type="text" placeholder="From" value="{{trailer.fromLocation}}"/>
        </div>
        <div class="col-sm-5 form-group">
          <label for="name">Destination</label>
          <input class="form-control" type="text" placeholder="To" value="{{trailer.toLocation}}" />
        </div>
        <div class="col-sm-3 form-group">
          <label for="name">Name</label>
          <input class="form-control" type="text" placeholder="Name" value="{{trailer.name}}"/>
        </div>
        <div class="col-xs-2">
          <button class="btn btn-danger" type="button" (click)="removeSavedItem(i)">Remove Entry</button>
        </div>
      </div>
    </div>
  </div>
</div>
<hr>
<div class="row" formArrayName="items" *ngFor="let item of getItems.controls; let i = index;" >
  <div class="form-group" [formGroupName]="i">
    <div class="col-md-5 form-group" >
      <label for="name">Origin</label>
      <input class="form-control" type="text" formControlName="origin" >
    </div>
    <div class="col-md-5 form-group">
      <label for="name">Destination</label>
      <input class="form-control" type="text" formControlName="to">
    </div>
    <div class="col-sm-3 form-group">
      <label for="name">Name</label>
      <input class="form-control" type="text" formControlName="name" placeholder="Name"/>
    </div>
    <div class="col-xs-2">
      <button class="btn btn-danger" type="button" (click)="removeItem(i)">Remove Entry</button>
    </div>
  </div>
</div>
<button class="btn btn-success" type="submit"  style="margin-right: 10px">Go</button>
<button class="btn btn-primary" type="button" (click)="addItem()" style="margin-right: 10px">New Box</button>

А вот как я создаю, добавьте и удалите элементы для FormArray:

get getItems(): FormArray {
  return this.boxForm.get('items') as FormArray;
}

get getSavedItems(): FormArray {
  return this.boxForm.get('savedItems') as FormArray;
}

createBox(): FormGroup {
  return this.formBuilder.group({
    name: ['', [Validators.required, Validators.minLength(3)]],
    origin: ['', [Validators.required, Validators.minLength(1)]],
    to: ['', [Validators.required, Validators.minLength(1)]]
  });
}

addItem(): void {
  this.getItems.push(this.createBox());
}

removeItem(index) {
  this.getItems.removeAt(index);
}

removeSavedItem(index) {
  this.getSavedItems.removeAt(index);
}

Вот stackblitz с воспроизводимым кодом моей проблемы.Если вы нажмете на «Удалить запись» над горизонтальной полосой, обе записи будут удалены из этого элемента в FormArray вместо только выбранного.

Почему это происходит?Я совершенно уверен, что это связано с двумя циклами for.Один для элементов управления saveItem и внутренний цикл для циклического перебора элементов в моем списке для заполнения FormArray, но я не могу точно определить проблему, я все еще изучаю свой путь с Angular

1 Ответ

1 голос
/ 08 мая 2019

Проблема заключается в создании FormArray -свойства savedItems, а также этой строки:

...
savedItems: this.formBuilder.array([this.createBox()])
...

Эти строки означают, что вы определяете только один FormGroup в вашем FormArray итак что у вас есть один элемент с index = 0.

В вашем файле шаблона вы в блоке для savedItems у вас есть два цикла:

1.) *ngFor="let item of getSavedItems.controls; let i = index;"

Это правильный цикл и даст вам правильную функциональностьдля removeAt.

2.) *ngFor="let trailer of trailerModelList; let x = index;"

Это неправильный цикл, поскольку вы не можете создавать FromArray -элементы из шаблона, как у вас сейчас.

Проблема вкратце: При нажатии кнопки Remove entry обе (все) savedItems будут удалены из массива, поскольку у вас есть только один элемент с индексом = 0 в FormArray.

Решение:

Шаг 1: Создайте для каждого trailerModelList -элемента FormArray с createBox() -методом.

  ngOnInit() {
    this.boxForm = this.formBuilder.group({
      items: this.formBuilder.array([this.createBox()]),
      savedItems: this.formBuilder.array([])
    });

    this.trailerModelList = new Array();
    this.trailerModelList.push(new TrailerModel(1, 'test', 'London', 'Paris'));
    this.trailerModelList.push(new TrailerModel(2, 'test2', 'Amsterdam', 'Berlin'));

    this.trailerModelList.forEach(item => {
      (this.boxForm.get('savedItems') as FormArray).controls.push(this.createBox(item.name, item.fromLocation, item.toLocation));
    });
  }

....

  createBox(name: string = null, origin: string = null, to: string = null): FormGroup {
    return this.formBuilder.group({
      name: [name, [Validators.required, Validators.minLength(3)]],
      origin: [origin, [Validators.required, Validators.minLength(1)]],
      to: [to, [Validators.required, Validators.minLength(1)]]
    });
  }

Шаг 2: Удалите следующую петлю из шаблона: *ngFor="let trailer of trailerModelList; let x = index;"

Шаг 3: Добавьте formControlName -объектэлементы формы внутри этой петли: *ngFor="let item of getSavedItems.controls; let i = index;"

<div class="row" formArrayName="savedItems" *ngFor="let item of getSavedItems.controls; let i = index;"  >
      <div>
        <div class="form-group" [formGroupName]="i" style="margin-bottom: 10px">
          <div>
            <div class="col-sm-5 form-group">
              <label for="name">Origin</label>
              <input class="form-control" type="text" placeholder="From" formControlName="origin"/>
            </div>
            <div class="col-sm-5 form-group">
              <label for="name">Destination</label>
              <input class="form-control" type="text" placeholder="To" formControlName="to" />
            </div>
            <div class="col-sm-3 form-group">
              <label for="name">Name</label>
              <input class="form-control" type="text" placeholder="Name" formControlName="name"/>
            </div>
            <div class="col-xs-2">
              <button class="btn btn-danger" type="button" (click)="removeSavedItem(i)">Remove Entry</button>
            </div>
          </div>
        </div>
      </div>
    </div>

Вот stackblitz с рабочим решением.

...