简体   繁体   中英

Angular reactive form with nested array

I have a complex nested array and I have the data in a object with nested array. I want to display all the data in edit view. I tried it in stackblitz and have issues in loading data . The link is enter link description here

I want to load second level array (groups) in the form text box. Thanks in advance.

You will have to create getters and in some cases, methods that return FormArray s.

Here's how:

import { Component, OnInit } from '@angular/core';
import { FormGroup, FormBuilder, FormArray } from '@angular/forms';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {

  data: any[];
  form: FormGroup;

  get tasks() {
    return ( < FormArray > this.form.get('tasks')).controls;
  }

  getGroupsFor(index) {
    return ( < FormArray > ( < FormArray > this.form.get('tasks')).controls[index].get('groups')).controls;
  }

  getDictionaryFor(index) {
    return ( < FormArray > ( < FormArray > this.form.get('tasks')).controls[index].get('dictionary')).controls;
  }

  getAttributesFor(taskIndex, groupIndex) {
    return ( < FormArray > ( < FormArray > ( < FormArray > this.form.get('tasks')).controls[taskIndex].get('groups')).controls[groupIndex].get('attributes')).controls;
  }

  constructor(private fb: FormBuilder) {}

  ngOnInit() {
    this.loadData();
    this.form = this.fb.group({
      lessoncode: 'TMM',
      countrycode: 'CA',
      languagecode: 'en',
      tasks: this.fb.array(this.getTasks())
    });
    console.log('Form Value', this.form.value);
  }

  getTasks() {
    return this.data.map(task => this.fb.group({
      taskid: task.taskid,
      taskname: task.taskname,
      groups: this.fb.array(this.getGroups(task.groups)),
      dictionary: this.fb.array(this.getDictionaries(task.dictionary))
    }));
  }

  getDictionaries(dictionaries: any[]) {
    return dictionaries.map(dictionary => this.fb.group({
      content_id: dictionary.content_id,
      term: dictionary.term,
      translation_id: dictionary.translation_id,
      value: dictionary.value,
      task_id: dictionary.task_id,
      task_dictionary_id: dictionary.task_dictionary_id,
      isnew: dictionary.isnew,
      altered: dictionary.altered
    }));
  }

  getGroups(groups: any[]) {
    return groups.map(group => this.fb.group({
      id: group.id,
      name: group.name,
      attributes: this.fb.array(this.getAttributes(group.attributes))
    }));
  }

  getAttributes(attributes: any[]) {
    return attributes.map(attribute => this.fb.group({
      name: attribute.name,
      contentid: attribute.contentid,
      value: attribute.value,
      translationvalue: attribute.translationvalue,
      placeholder: attribute.placeholder,
      label: attribute.label,
      defaultvalue: attribute.defaultvalue,
      type: attribute.type,
      element: attribute.element,
      altered: attribute.altered,
      translation_id: attribute.translation_id,
      isnew: attribute.isnew
    }));
  }

  loadData() {
    this.data = [{
        "taskid": 31,
        "taskname": "intro",
        "groups": [{
          "id": 223,
          "name": "Fullscreen Image and Sub-Heading",
          "attributes": [{
              "name": "Main Heading",
              "contentid": 767,
              "value": "Multitasking",
              "translationvalue": "Realización de varias tareas al mismo tiempo",
              "placeholder": "Main Heading",
              "label": "Main Heading",
              "defaultvalue": "",
              "type": "text",
              "element": "input",
              "altered": false,
              "translation_id": 3063,
              "isnew": false
            },
            {
              "name": "Sub-Heading",
              "contentid": 155,
              "value": "Driver Attitude",
              "translationvalue": "Actitud del conductor",
              "placeholder": "Type Heading",
              "label": "Sub-Heading",
              "defaultvalue": "",
              "type": "text",
              "element": "input",
              "altered": false,
              "translation_id": 3064,
              "isnew": false
            },
            {
              "name": "Full-Screen Image",
              "contentid": 211,
              "value": "/media/lessons/dst/intro/image01-right.jpg",
              "translationvalue": null,
              "placeholder": "Image Url",
              "label": "Full-Screen Image",
              "defaultvalue": "",
              "type": "image",
              "element": "input",
              "altered": false,
              "translation_id": null,
              "isnew": true
            },
            {
              "name": "Full-Screen Image",
              "contentid": 212,
              "value": "/media/lessons/dst/intro/image01-left.jpg",
              "translationvalue": null,
              "placeholder": "Image Url",
              "label": "Full-Screen Image",
              "defaultvalue": "",
              "type": "image",
              "element": "input",
              "altered": false,
              "translation_id": null,
              "isnew": true
            },
            {
              "name": "Full-Screen Image",
              "contentid": 213,
              "value": "/media/lessons/dst/intro/image01-right.jpg",
              "translationvalue": null,
              "placeholder": "Image Url",
              "label": "Full-Screen Image",
              "defaultvalue": "",
              "type": "image",
              "element": "input",
              "altered": false,
              "translation_id": null,
              "isnew": true
            },
            {
              "name": "Full-Screen Image Alt",
              "contentid": 880,
              "value": "Multitasking - Driver Attitude",
              "translationvalue": "Multitasking - Driver Attitude",
              "placeholder": "Full-Screen Image Alt",
              "label": "Full-Screen Image Alt",
              "defaultvalue": "",
              "type": "alt",
              "element": "input",
              "altered": false,
              "translation_id": 3062,
              "isnew": false
            },
            {
              "name": "Icon SVG Data",
              "contentid": 3063,
              "value": "",
              "translationvalue": null,
              "placeholder": "SVG Data",
              "label": "Icon SVG Data",
              "defaultvalue": "",
              "type": "html",
              "element": "textarea",
              "altered": false,
              "translation_id": null,
              "isnew": true
            }
          ]
        }],
        "dictionary": [{
          "content_id": 5,
          "term": "Continue",
          "translation_id": 3065,
          "value": "Continuar",
          "task_id": 31,
          "task_dictionary_id": 11,
          "isnew": 0,
          "altered": 0
        }]
      },
      {
        "taskid": 32,
        "taskname": "question-1",
        "groups": [{
          "id": 228,
          "name": "Question",
          "attributes": [{
              "name": "Question Text",
              "contentid": 956,
              "value": "Welcome to the Multitasking exercise. Before we begin, please select the statement that best describes your current view on the subject.",
              "translationvalue": "Bienvenido al ejercicio sobre realización de varias tareas al mismo tiempo. Antes de comenzar, seleccione la afirmación que mejor describa su opinión actual sobre el tema.",
              "placeholder": "Question Text",
              "label": "Question Text",
              "defaultvalue": "",
              "type": "textarea",
              "element": "textarea",
              "altered": false,
              "translation_id": 3462,
              "isnew": false
            },
            {
              "name": "Randomize Answers",
              "contentid": 1100,
              "value": "1",
              "translationvalue": null,
              "placeholder": "Randomize Answers",
              "label": "Randomize Answers",
              "defaultvalue": "2",
              "type": "truefalse",
              "element": "select",
              "altered": false,
              "translation_id": null,
              "isnew": true
            }
          ]
        }],
        "dictionary": []
      }
    ];
  }
}

And this is going to be your Template:

<form [formGroup]="form">
  <input type="text" formControlName="lessoncode" />
  <input type="text" formControlName="countrycode" />
  <input type="text" formControlName="languagecode" />

  <div formArrayName="tasks">
    <div *ngFor="let task of tasks;let taskIndex=index;">
      <h1>Tasks</h1>
      <div [formGroupName]="taskIndex">
        <input formControlName="taskid" />
        <input formControlName="taskname" />
        <div formArrayName="groups">
          <div *ngFor="let group of getGroupsFor(taskIndex);let groupIndex=index;">
            <h2>Group</h2>
            <div [formGroupName]="groupIndex">
              <input formControlName="id" />
              <input formControlName="name" />
              <div formArrayName="attributes">
                <div *ngFor="let attribute of getAttributesFor(taskIndex, groupIndex);let attributeIndex=index;">
                  <h3>Attribute</h3>
                  <div [formGroupName]="attributeIndex">
                    <input formControlName="name" />
                    <input formControlName="contentid" />
                    <input formControlName="value" />
                    <input formControlName="translationvalue" />
                    <input formControlName="placeholder" />
                    <input formControlName="label" />
                    <input formControlName="defaultvalue" />
                    <input formControlName="type" />
                    <input formControlName="element" />
                    <input formControlName="altered" />
                    <input formControlName="translation_id" />
                    <input formControlName="isnew" />
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>

        <div formArrayName="dictionary">
          <div *ngFor="let dict of getDictionaryFor(taskIndex); let dictIndex=index;">
            <h2>Dictionary</h2>
            <div [formGroupName]="dictIndex">
              <input formControlName="content_id" />
              <input formControlName="term" />
              <input formControlName="translation_id" />
              <input formControlName="value" />
              <input formControlName="task_id" />
              <input formControlName="task_dictionary_id" />
              <input formControlName="isnew" />
              <input formControlName="altered" />
            </div>
          </div>
        </div>

      </div>
    </div>
  </div>
</form>

I've literally spent about an hour creating this for you. But this was fun. Here's a StackBlitz for your referece .

Hope it helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM