Angular 2+: независимый доступ к реактивным формам с проверкой в ​​цикле ngFor - PullRequest
0 голосов
/ 25 января 2020

Я работаю с Реактивной формой. У меня есть 2 набора данных. Это:

  1. Список элементов - Содержит идентификатор и имя элемента
  2. Список групп - Содержит идентификатор и имя группы

Вот что я пытаюсь сделать:

  1. В пользовательском интерфейсе я перебираю элементы и показываю идентификатор элемента и элемент Имя. Работает нормально.
  2. Я перебираю группы и показываю идентификатор группы и имя группы в поле выбора. Также работает нормально.
  3. Я помещаю поле Выбрать из пункта 2 выше, в ngFor l oop Предметов в пункте 1 выше, так что каждый Элемент может быть назначен Группе . Допустим, я нажимаю на первое поле «Выбрать» с целью назначения группы из списка для первого элемента. Затем вместо того, чтобы щелкнуть по любой из показанных опций, я щелкаю прочь где-то еще на странице. В этом действии также отображается сообщение об ошибке для всех других элементов управления формой / полей выбора на странице. Если я выберу значение для любого из других полей выбора в остальной части страницы, то сообщение об ошибке для четного первый выпадающий список очищается. Это проблема, и это не должно происходить. Ошибка должна отображаться только для поля «Выбор», связанного с первым элементом, а не для других полей выбора на странице, которые должны быть связаны с другими элементами. Каждая из этих ошибок должна отображаться независимо для каждой из этих форм.

РЕЗЮМЕ ВЫПУСКА:

Я пытаюсь назначьте группу каждому из этих пунктов . Поэтому я пытаюсь исправить (выше) связанное поведение форм, чтобы каждая форма работала независимо от другой в l oop и после выбора группы, когда " Нажата кнопка «Назначить группу» , я пытаюсь получить доступ к соответствующему идентификатору элемента и идентификатору группы только из отправленной формы, а не из других форм. Как этого можно добиться с помощью надлежащей проверки / ошибок, отображаемых для отправленных форм, как и когда к ним обращаются?

ЖИВОЙ ДЕМО ПРОБЛЕМЫ:

У меня есть здесь уже установлена ​​ демонстрация StackBlitz , повторяющая проблему.

КОД РЕДАКТОРА LIVE DEMO:

Вот код редактора демо-версии *

Ответы [ 3 ]

1 голос
/ 27 января 2020

на самом деле с вашим кодом angular понимаем, что есть одна форма (formControlName) с именем partnerGroupsId, поэтому все они связаны с одинаковым идентификатором и именем

РЕШЕНИЕ РЕАЛЬНОГО ВРЕМЕНИ: https://angular-2-accessing-reactive-forms-independently.stackblitz.io

КОД РЕАЛЬНОГО РЕДАКТИРОВАНИЯ: https://stackblitz.com/edit/angular-2-accessing-reactive-forms-independently

РЕШЕНИЕ:

Вам необходимо l oop через ваши данные (this.allData) для построения сформируйте группы Builder:

const groups = {};

for(let i = 0; i< this.allData.length; i++) {
  groups['partnerGroupsId' + i] = ['', [
            Validators.required,
  ]];
}

this.applicationForm = this.formBuilder.group(
        groups
);

и используйте ниже HTML:

<ul class="pb-0">
<ng-container *ngFor="let item of allData; let i = index">
    <li>
        <label class="label">
            {{item.item_name}} /
             <span class="label-heading">Item ID # {{item.item_id}}</span>
        </label>
    <form [formGroup]="applicationForm" (ngSubmit)="assignGroup()"
          (keyup.enter)="assignGroup()"
          class="full-width">
          <label position="floating">Select Group</label>
          <select formControlName="partnerGroupsId{{ i }}">
            <option value="">Select a Group from this list</option>
              <option *ngFor="let partnerGroups of allDataGroups;"
                      value="{{partnerGroups.group_id}}" selected>
                  {{partnerGroups.display_name}}
              </option>                  
          </select>
      <div class="validaterrors">
          <ng-container *ngFor="let validation of validationMessages.partnerGroupsId;"   >
              <div class="error-message"
                    *ngIf="applicationForm.get('partnerGroupsId' + i).hasError(validation.type) && (applicationForm.get('partnerGroupsId' + i).dirty || applicationForm.get('partnerGroupsId' + i).touched)">
                  {{ validation.message }}
              </div>
          </ng-container>
      </div>

        <button color="primary" expand="block" type="submit" class="">
            Assign Group
        </button>
    </form>
    </li>
</ng-container>

0 голосов
/ 27 января 2020

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

<div *ngFor="let item of group">
   <custom-form [item]="item"></custom-form>
</div>

Все, что происходит в пользовательской форме, остается в пользовательской форме, что вам и нужно. Конечно, вы можете использовать eventEmitter, если хотите отправить результат по цепочке.

0 голосов
/ 25 января 2020

l oop, который вы используете внутри шаблона, создает несколько форм, использующих один и тот же FormControl. Есть несколько способов исправить это, один с помощью FormArray, но я думаю, что использование атрибута item_id для идентификатора FormControl является самым простым способом получить доступ к элементу управления в шаблоне с помощью form.controls[id]

  form: FormGroup = new FormGroup({});
  allData = [
            {
                "item_name": "Test 1",
                "item_id": "1",
            },
            {
                "item_name": "Test 2",
                "item_id": "2",
            },
            {
                "item_name": "Test 3",
                "item_id": "3",
            },
            {
                "item_name": "Test 4",
                "item_id": "4",
            },
            {
                "item_name": "Test 5",
                "item_id": "5",
            },
        ];
  allDataGroups = [
            {
                "display_name": "Group 1",
                "group_id": "1",
            },
            {
                "display_name": "Group 2",
                "group_id": "2",
            },
            {
                "display_name": "Group 3",
                "group_id": "3",
            }
        ];

  constructor() {
    this.createFormControls()
  }

  private createFormControls() {
    for (const datum of this.allData) {
      const id = datum.item_id;
      this.form.addControl(id, new FormControl())
    }
  }
<div class="container">
  <form [formGroup]="form">
    <div *ngFor="let datum of allData">
      <span>{{ datum.item_name }} / Item ID #{{ datum.item_id }}</span>
      <select style="display: block" [formControlName]="datum.item_id">
        <option *ngFor="let group of allDataGroups" [value]="group.group_id">
          {{ group.display_name }}
        </option>
      </select>
      <button>Assign Group</button>
    </div>
  </form>
</div>
...