Как привязать массив объектов к formGroup и formarray, используя angular8 - PullRequest
0 голосов
/ 23 февраля 2020

Привет, я использовал реактивные формы для привязки массива объектов к formArray, но здесь, если я выберу какой-либо один элемент в одном разделе и нажму кнопку перемещения вправо / перемещения влево, тогда весь объект будет перемещен из одного раздела в Другой. Но эта функциональность работает нормально, но я не могу обнаружить изменения, сделанные из одного раздела в другой в form.valuechanges (). Может ли кто-нибудь помочь мне обнаружить изменения, если элементы перемещены из одного раздела в другой, и здесь я хочу, чтобы обнаружение изменений было выполнено, но функциональность должна работать как есть, я имею в виду весь объект, который нужно переместить из одного раздела в другой.

Заранее спасибо.

У меня есть рабочая демо-версия 2, я хочу, чтобы моя ранее опубликованная демо-версия работала так же, как эта демо-2, с работой на формации. ДЕМО 2

ДЕМО: ДЕМО 1

TS:

 private settingsGroupInfoForm() {
    if (!this.agentDetailsList) {
      // Add
     this.agentGroupViewInfoForm = this.FB.group({
          agentGroupView: this.FB.array(
            this.agentInView.map(x=>(x))
          ),
        })
    } else {
      // Edit
      if (this.agentDetailsList) {

       this.agentGroupViewInfoForm = this.FB.group({
          agentGroupView: this.FB.array(this.agentInView.map(x=>(x))),

      })
      }
      this.agentGroupViewInfoForm.valueChanges.subscribe(data => {
          this.formEdit = true;
          console.log('agentGroupViewInfoForm', this.formEdit)
        })
      }
    }

HTML:

 <div class="card-body overflow-auto py-0" *ngIf="agentGroupViewInfoForm"
            [formGroup]="agentGroupViewInfoForm">
                <ul class="list-group list-group-flush" *ngFor="let child of agentInView"   name="agentInGroup" formArrayName="agentGroupView">
                  <li class="list-group-item {{isInActiveItems(child) ? 'active' : ''}}" (click)="toggleActiveItem(child)">
                    {{child.value}}
                  </li>
                </ul>
              </div>

1 Ответ

2 голосов
/ 27 февраля 2020

Ваша проблема

  • У вас есть 2 массива элементов одного типа
  • Вы хотите отобразить массив форм для каждого массива
  • Вы хотите быть возможность перемещать элементы между массивами
  • Вы хотите иметь возможность привязать значения формы обратно к элементам при отправке

Дизайн

Как и в большинстве случаев каждая проблема, связанная с компонентами в Angular, вы должны сначала подумать о модели. Ваша модель - король, а все остальное построено вокруг нее.

В вашей демонстрации вы перемещаете элементы между списками. Вы обновляете свою модель и привязываете к ней HTML. В этом нет ничего плохого - это правильный подход и работает.

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

В абстрактных терминах у вас есть

list1: [];
selected1: [];

list2: [];
selected2: [];

Если вы Если вы хотите переместить элементы с 1 -> 2, ваш метод перемещения удалит все выбранные элементы с items1 до items2. Просто.

Как только вы добавите формы, у вас будет такая структура:

list1: [];
selected1: [];
form1: FormGroup;
formArray1: FormArray;

list2: [];
selected2: [];
form2: FormGroup;
formArray2: FormArray;

И когда вы будете перемещать элементы с 1 -> 2, вы продолжите перемещать элементы с list1 на list2, но теперь вам также необходимо удалить связанный элемент из formArray1 и добавить его к formArray2.

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

Создание формы

Работа с массивами форм, пожалуй, самая сложная часть этого ответа. Ключ с массивами форм заключается в том, что структура HTML имитирует структуру создаваемого вами объекта FormGroup.

Мы можем использовать FormBuilder для создания формы из массива и привязки к ней следующим образом:

component.ts

buildForm() {
  this.model = [ 
    { value: 'a' }, { value: 'b' }, { value: 'c' }
  ];

  // create a form group for each item in the model
  const formGroups = this.model.map(x => this.formBuilder.group({
    value: this.formBuilder.control(x.value)
  }));

  // create a form array for the groups
  const formArray = this.formBuilder.array(formGroups);

  // create the top-level form
  this.form = this.formBuilder.group({
    array: formArray
  });
}

И привязки к ней в HTML примерно так:

<form [formGroup]="form1" (submit)="onSubmit()">
  <div formArrayName="array">
    <div *ngFor="let item of list1; let i = index" [formGroupName]="i">
      <input formControlName="value" />
    </div>
  </div>
  <button>Submit</button>
</form>

Это сгенерирует вход для каждого элемента в массиве, содержащий значения "a", "b", "c" соответственно.

Перемещение элементов

Перемещение элементов между массивами - простая javascript проблема. Нам нужно splice исходный массив и push к целевому массиву.

Чтобы переместить элементы из списка 1 в список 2:

// move selected items from model 1
this.selected1.forEach(item => {
  const index = this.list1.indexOf(item);
  this.list1.splice(index, 1);
  this.list2.push(item);
});

this.selected1.length = 0;

Это будет через l oop каждый выбранный элемент в списке 1, склейте его из списка, добавьте его в список 2. Затем он очистит выбранные элементы;

Перемещение групп форм

Вы переместите группы форм одновременно с перемещением предметов. Это похоже на концепцию - вы удаляете из одного и добавляете к другому. Вы построили массив форм из своей модели, так что вы знаете, что ваши индексы совпадают.

// move selected items from model 1
this.selected1.forEach(item => {
  const index = this.list1.indexOf(item);
  const formGroup: FormGroup = this.formArray1.controls[index] as FormGroup;

  this.list1.splice(index, 1);

  // move between form arrays
  this.formArray1.removeAt(index);
  this.formArray2.push(formGroup);

  this.list2.push(item);
});

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

formArray.removeAt(index) и formArray.push(formGroup) делают движение. Разница с массивом форм заключается в том, что нам нужно сначала получить ссылку на него, используя this.formArray1.controls[index] as FormGroup;.

DEMO: https://stackblitz.com/edit/angular-3cwnsv

Внимание

В этом проекте важен порядок, в котором вы удаляете массивы и формы и добавляете их в них. Вы привязываете HTML к своим массивам и своей форме. Вы создаете массив входных данных, циклически перебирая свой массив и привязывая каждый элемент к i-й группе в массиве форм. Если вы сначала удалите из формы, теперь у вас будет n элементов в массиве и n - 1 элементов в вашем массиве форм. У вас будет ошибка при попытке привязки к неопределенной n-й группе форм.

Теперь вы выполняете транзакцию с несколькими операциями.

Помимо обеспечения удаления и добавления в правильный порядок, один из способов - использовать OnPush обнаружение изменений. Читайте об этом, так как это хорошая стратегия для всех, кроме самых простых приложений.

Следующие шаги

Я оставил свою демонстрацию простой для целей ответа. Это не особенно масштабируемый или многоразовый, как он есть. Существует много повторяющихся кодов и неправильных имен, чтобы не отвлекаться на вложенные компоненты и имена свойств, относящиеся к вашему приложению.

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

...