Angular5 Reactive Forms: Nested Form Arrays

I'm currently facing a challenge with integrating a FormArray within another FormArray. I've been struggling to find a solution for this issue.

Here is the relevant part of my TypeScript file:

createForm() {
    this.myForm = this.formBuilder.group({
        people: this.formBuilder.array([
            { addresses: this.formBuilder.array([]) }
        ])
    });
}

In essence, I want to create a people FormArray where each individual can have multiple addresses. In my HTML, I attempt to represent it like so:

<div [formGroup]="myForm">
    <div formArrayName="people">
        <div *ngFor="let person of people.controls; let i=index">
            Person {{ i + 1 }}

            <div *ngFor="let address of person.addresses.controls; let j=index">
                Address {{ j + 1 }}
            </div>
        </div>
    </div>
</div>

This example is simplified, and my actual form will be more complex. My script includes an "Add person" link that triggers a function pushing an object to the people FormArray.

Upon calling createForm(), I encounter the following errors in the browser:

ERROR TypeError: this.form._updateTreeValidity is not a function
ERROR TypeError: this.form.get is not a function

Where did I make a mistake? How can I achieve what I intend to do? Any guidance would be greatly appreciated!

Answer №1

If you're looking for an example, consider trying something similar to this:

Check out the StackBlitz example here

Here's the basic structure in HTML:

<form [formGroup]="myForm" (ngSubmit)="submit()">
    <div formArrayName="people">
        <div *ngFor="let person of getPeople(myForm); let i=index">
            <div style="margin: 5px;" [formGroupName]="i">
                <label>Person {{ i + 1 }}</label>
                <input type="text" placeholder="Name" formControlName="name">
                <button *ngIf="i<1" (click)="addPeople()" type="button">Add People</button>

                <div formArrayName="addresses">
                    <div *ngFor="let address of getAddress(person); let j=index">
                        <div [formGroupName]="j">
                            <span>Address {{ j + 1 }}</span>
                            <input type="text" placeholder="house No" formControlName="houseNo">
                            <input type="text" placeholder="city" formControlName="city">
                            <button *ngIf="j<1" (click)="addAddress(i)" type="button">+</button>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</form>

<div style="margin-top: 20px;">
    {{myForm.value | json}}
</div>

In TypeScript:

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

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

  constructor(private fb: FormBuilder) {}

  ngOnInit() {
    this.createForm();
  }

  createForm() {
    this.myForm = this.fb.group({
      people: this.fb.array([this.createPeopleArray()])
    })
  }

  createPeopleArray() {
    return this.fb.group({
      name: null,
      addresses: new FormArray([
        this.createAddressArray()
      ])
    });
  }

  getPeople(form) {
    return form.controls.people.controls;
  }

  getAddress(form) {
    return form.controls.addresses.controls;
  }

  createAddressArray() {
    return this.fb.group({
      houseNo: null,
      city: null
    })
  }

  addPeople() {
    const control = <FormArray>this.myForm.get('people');
    control.push(this.createPeopleArray());
  }

  addAddress(i) {
    const control = <FormArray>this.myForm.get('people').controls[i].get('addresses');
    // console.log(control);
    control.push(this.createAddressArray());
  }

  submit() {
    console.log(this.myForm.value)
  }
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Troubleshooting problem with Angular ngx-bootstrap datepicker positioning on mobile devices

Having an issue with ngx-bootstrap/datepicker, it works fine on larger screens but not on mobile screens. Any assistance would be appreciated. https://i.sstatic.net/ZGdyQ.png When the screen size is reduced to mobile (even on actual mobile devices), it o ...

Node OOM Error in Webpack Dev Server due to Material UI Typescript Integration

Currently in the process of upgrading from material-ui v0.19.1 to v1.0.0-beta.20. Initially, everything seems fine as Webpack dev server compiles successfully upon boot. However, upon making the first change, Node throws an Out of Memory error with the fol ...

Issue encountered while executing Angular 6 Single Page Application

I am currently working on building a new Angular 6 SPA using Visual Studio 2017 Community. However, I am encountering an error when trying to run the project: An unhandled exception occurred while processing the request. NodeInvocationException: rxjs.me ...

Refresh the page in Angular2

I am struggling to make Ng2 refresh the page after adding a new entry. This is necessary for my CRUD system, as I want the page to update automatically when a new entry is successfully added. The issue arises because the table is populated based on code en ...

environment variable process.env is not defined

In my React/Typescript code, I am encountering an issue with accessing an environment variable using process.env. While I can successfully access the NODE_ENV variable, attempts to access CURRENT_URL result in it returning undefined. console.log(process.en ...

How can you determine the number of times a particular digit appears around a specific position in a TypeScript array

(Utilizing Typescript for assistance) I am looking to determine the number of occurrences of the digit 2 surrounding a specific position within an array. The function takes in the position coordinates as parameters - param 1 for row and param 2 for column. ...

Tips for effectively highlighting search text within HTML content without causing any issues

I am in search of a solution that can assist me in searching for specific terms within an HTML string while also highlighting them. I have the ability to remove the HTML content from the string, but this poses the problem of losing the context of the origi ...

Encountering difficulties launching a simple Angular 2 application

I am in the process of setting up an Angular App using angular CLI by following the steps outlined on the official Angular website. However, when I enter the command ng serve and attempt to access the URL http://localhost:4200/ The page remains stuck on ...

Creating paths on-the-fly from GraphQL API within Nextjs

Having trouble accessing individual project pages from my project list. Keep encountering a 404 error page instead. I've attempted to retrieve the data using both simple Fetch and ApolloClient, but the bug persists. Error messages like 'could n ...

PHP constantly generates fresh sessions without fail

In the process of developing a website with Angular 2 and a PHP REST API backend, I encountered an issue related to session data management. I noticed that every request from the website was creating a new session file, a behavior that was not replicated w ...

What is the process of transitioning a user from being able to select only one checkbox to having the ability to select multiple checkboxes in Angular?

I am working on an angular app where I want the user to only be able to select one checkbox from a selection list when they click on a "check me" checkbox. However, if the "check me" checkbox is not selected, then the user should be able to choose multiple ...

ag-grid provides unique filter options for custom date filtering in Angular 2

Currently, I am attempting to assign new options to a date column field by using the following method. However, these new options are not being displayed in the grid. let dateValues = ["equals", "inRange","quarter1","quarter2","quarter3","quarter4"]; { ...

Encountering a 'Uncaught SyntaxError: Unexpected Token <' error when deploying Angular2 on Heroku with all external references

As I attempt to deploy my angular4 app on Heroku, I encounter errors with all the .js references linked from my .html. The errors I am facing are: 16:29:54.613 myapp.herokuapp.com/:1 Resource interpreted as Stylesheet but transferred with MIME type text/ ...

The CORS policy specified in next.config.js does not appear to be taking effect for the API request

I am currently working on a Next.js application with the following structure: . ├── next.config.js └── src / └── app/ ├── page.tsx └── getYoutubeTranscript/ └── getYoutubeTranscript.tsx T ...

Using Iframe for WooCommerce integration and implementing Facebook login within an Ionic application

I have created an Ionic application that includes an iframe from a Wordpress website. Here is the code snippet from my home.page.ts file: import { Component } from '@angular/core'; import { DomSanitizer } from "@angular/platform-browser"; @Com ...

Stop a form submission if any of its input fields are missing required values

Currently, when the contact form is submitted with an input value other than 4, a success message "Thanks, I'll get back to you soon!" appears and then the form is cleared. How can I modify this so that if an input value other than 4 is entered, the f ...

echarts line and area chart experiencing a scaling issue

When I incorporate both a line and an area in the same chart, along with a button to change the data source, sometimes pressing the button results in a scaling issue. The data itself remains accurate, but the displayed area may be cut off in certain parts ...

define elements within feature modules

Currently, I am working on an Angular project that has a main module called 'admin' which includes 3 feature modules. In this setup, there is a particular component that needs to be used in both the first and second modules. I attempted importin ...

Outside the observable in Angular, there is a vacant array

Within my Angular application, I am facing an issue with the following code snippet located inside a method: let cardArray: string[] = []; this.cardService.getCards().subscribe((cards) => { console.log("1", cards); for (const card of car ...

What is the best way to retain an edited value within the same index without moving it to a different

One issue I encounter is when attempting to save an edited value on the same index, but the value cannot be saved because the editing mode has not been closed. This pertains to a TypeScript File where I need to save the edited value in a selected Command ...