Angular: FormArray не повторяется - PullRequest
1 голос
/ 18 июня 2020

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

У меня есть форма, где элементом управления является массив из JSON. Я создал для этого реактивную форму. Ниже мой JSON и мой код TS:

JSON (получено из бэкэнд-запроса)

{
    "questionList": [
        {
            "questionCategory": {
                "questionCategoryName": "JAVA",
                "id": 40,
                "isActive": true,
                "timestamp": "2020-06-12 14:06:47.325"
            },
            "difficultyLevel": 0,
            "options": [
                {
                    "answer": false,
                    "id": 2,
                    "optionText": "method",
                    "timestamp": "2020-06-18 17:17:11.75"
                },
                {
                    "answer": false,
                    "id": 3,
                    "optionText": "name",
                    "timestamp": "2020-06-18 17:17:11.753"
                },
                {
                    "answer": false,
                    "id": 4,
                    "optionText": "class",
                    "timestamp": "2020-06-18 17:17:11.758"
                },
                {
                    "answer": true,
                    "id": 1,
                    "optionText": "variable",
                    "timestamp": "2020-06-18 17:17:11.663"
                }
            ],
            "section": {
                "marksPerQuestion": 3,
                "id": 8,
                "isActive": true
            },
            "id": 1,
            "isActive": true,
            "questionText": "What is a variable ?",
            "timestamp": "2020-06-18 17:17:10.946"
        },
        {
            "questionCategory": {
                "questionCategoryName": "APTITUDE",
                "id": 41,
                "isActive": true
            },
            "difficultyLevel": 0,
            "options": [
                {
                    "answer": true,
                    "id": 6,
                    "optionText": "xyz",
                    "timestamp": "2020-06-17 21:50:48.975"
                },
                {
                    "answer": true,
                    "id": 5,
                    "optionText": "abc",
                    "timestamp": "2020-06-17 21:50:48.907"
                }
            ],
            "section": {
                "marksPerQuestion": 2,
                "id": 7,
                "isActive": true,
                "timestamp": "2020-06-12 14:08:14.181"
            },
            "id": 2,
            "isActive": true,
            "questionText": "What is def",
            "timestamp": "2020-06-17 21:50:48.6"
        }
    ],
    "empty": false
}

Код TS для этого JSON

updateQuestionForm = this.fb.group({
  id: [], isActive: [], difficultyLevel: [0], questionText: [''],
  questionCategory: this.fb.group({
    id: [],
    questionCategoryName: ['']
  }),
  section: this.fb.group({
    id: [],
    marksPerQuestion: ['']
  }),
  options: new FormArray([])
});

optionForm = this.fb.group({
  id: [], optionText: [''], answer: []
});

onEdit(e) {
  const formArray: FormArray = this.updateQuestionForm.get('options') as FormArray;
  this.updateQuestionForm.controls['id'].setValue(e.id);
  this.updateQuestionForm.controls['isActive'].setValue(e.isActive);
  this.updateQuestionForm.controls['questionText'].setValue(e.questionText);
  this.updateQuestionForm.controls['questionCategory'].setValue({
    id: e.questionCategory.id,
    questionCategoryName: e.questionCategory.questionCategoryName
  });
  this.updateQuestionForm.controls['section'].setValue({
    id: e.section.id,
    marksPerQuestion: e.section.marksPerQuestion
  });
  for(let i of e.options) {
    this.optionForm.controls['id'].setValue(i.id);
    this.optionForm.controls['optionText'].setValue(i.optionText);
    this.optionForm.controls['answer'].setValue(i.answer);
    formArray.push(new FormControl(this.optionForm.value));
  }
  console.log(this.updateQuestionForm.value);
}

get Status() {
  return this.updateQuestionForm.get('isActive');
}

get Options(): FormArray {
  return this.updateQuestionForm.get('options') as FormArray;
}

Позвольте мне объяснить, что утверждает TS: Во-первых, я создаю форму updateQuestionForm, которая является основной формой для JSON. Вторая форма optionForm предназначена для options FormArray updateQuestionForm. Я создал эту вторую форму, потому что мне нужны определенные элементы управления из массива. Так что это запомнилось мне. Метод onEdit() запускается нажатием кнопки, которая извлекает JSON из Mat-Table.

Форма HTML

<form [formGroup]="updateQuestionForm" (submit)="onUpdateQuestionForm()">
  <div class="row">
    <div class="col-md-4">
      <mat-form-field>
        <mat-label>Enter Question</mat-label>
        <input matInput formControlName="questionText">
      </mat-form-field>
    </div>
    <div class="col-md-3">
      <mat-form-field formGroupName="questionCategory">
        <mat-label>Question Category</mat-label>
        <mat-select formControlName="id">
          <ng-container *ngFor="let q of QuestionCategory;">
            <mat-option [value]="q.id">{{ q.questionCategoryName }}</mat-option>
          </ng-container>
        </mat-select>
      </mat-form-field>
    </div>
    <div class="col-md-3">
      <mat-form-field formGroupName="section">
        <mat-label>Marks</mat-label>
        <mat-select formControlName="id">
          <ng-container *ngFor="let m of Marks;">
            <mat-option [value]="m.id">{{ m.marksPerQuestion }}</mat-option>
          </ng-container>
        </mat-select>
      </mat-form-field>
    </div>
    <div class="col-md-2">
      <mat-label>Status</mat-label><br>
      <mat-slide-toggle color="primary" formControlName="isActive">{{ Status ? 'Active' : 'Inactive' }}</mat-slide-toggle>
    </div>
  </div>
  <h3>Options & Answers</h3>
  <div formArrayName="options">
    <div class="row" *ngFor="let o of Options.value; index as i" [formGroupName]="i">
      <div class="col-md-6">
        <mat-form-field>
          <mat-label>Option</mat-label>
          <input matInput formControlName="optionText">
        </mat-form-field>
      </div>
      <div class="col-md-3">
        <mat-label>Answer</mat-label><br>
        <mat-slide-toggle color="primary" formControlName="answer">
           {{ answer ? 'True' : 'False' }}
        </mat-slide-toggle>
      </div>
    </div>
  </div>
  <button mat-flat-button type="submit" style="background-color: #28a745; color: white;">Update</button>
</form>

Это это форма JSON. Я успешно могу получить и сохранить значения для элементов управления questionCategory, section, isActive, questionText. Проблема возникает для элемента управления options. У меня есть 4 варианта (4 optionText, 4 answer каждый извлекается из базы данных; см. Образец JSON выше ). Но я не могу отобразить элементы управления. Похоже, что ngFor внутри formArrayName="options" не работает. После h2 ничего не приходит.

Помогите пожалуйста. К вашему сведению, я следовал этой ссылке для части цикла formArrayName.

Here's the initial view

1 Ответ

1 голос
/ 18 июня 2020

В вашем случае вам не нужны две формы для обновления данных вопроса, и ваш код выглядит сложным.

Я упростил ваш код, и он отлично работает. Вы можете проверить это здесь .

Что я сделал?

1) По сути, я создал простую структуру формы в ngOnInit() на основе ваших примеров кода.

2) Я написал функцию updateQuestionData(), в которой я исправляю форму данными JSON. Я перебрал options и создал группу форм для каждого option.

Вы можете изменить значения в форме и посмотреть, как обновляется updateQuestionForm.

I надеюсь, что это упростит ваш вариант использования и оптимизирует ваш код.

...