How to access individual reactive form instances within an ngFor loop in Angular

I've been grappling with this issue for a few hours now, trying to find a solution that doesn't involve adding fields dynamically. All I need is the ability to access the properties of each form instance, but currently, it only displays one instance.

Check out the StackBlitz: https://stackblitz.com/edit/angular-dzzzql

HTML

<section class="exercises">
  <form
    fxLayout="column"
    fxLayoutGap="2px"
    [formGroup]="exerciseForm"
    (ngSubmit)="onSubmit(exerciseForm.value)"
  >

    <ul *ngFor="let exercise of exercises">
      <li>{{ exercise.instruction }}</li>
      <ul *ngFor="let question of exercise.questions; let i = index">
        <li>
         {{ question.prefix }}
          <mat-form-field>
            <input
              name="answer"
              type="text"
              id="answer"
              matInput
              formControlName="answer">
          </mat-form-field>

          {{ question.sufix }} -
          {{ question.translation }}
        </li>
      </ul>
    </ul>
    <button type="submit" mat-raised-button color="primary">Submit</button>
  </form>
</section>

Typescript

exercises: Exercise[]=[
    new Exercise (
      'Answer this question',
      [new Question (1,'Eu','maluco','I am crazy'),
       new Question (2,'Eu','doidinho','I am cuckoo')],
    )]

constructor(private fb: FormBuilder) { }

exerciseForm = this.fb.group({
    answer:['']
  })
ngOnInit(): void {

  }

onSubmit(answer: Answer) {
  console.log(this.exerciseForm.value)
}
}

Answer №1

If you're using the same formcontrolName, only the last control value will be received.

So, how can we make changes to your code?

In app.component.ts

Replace:

exerciseForm = this.fb.group({
    answer:['']
  })

With:

exerciseForm:FormGroup;

Simply initialize the formgroup here without assigning any value for now.

You need to add a new function to create the formGroup and call it inside the ngOnInit lifecycle hook.

ngOnInit(): void {
    this.createGroup()
}

Instead of assigning this.exerciseForm earlier, assign the group value with this.fb.group({});.

Then, you will need form controls for the questions which are in an array, iterate over them in ts like,

this.exercises[0].questions.forEach(control => ... )

Within this loop, assign each item respectively to control. Since id is unique, use it as the control like so,

this.exerciseForm.addControl(control.id, this.fb.control(''))

The function should look like this,

createGroup(){
    this.exerciseForm = this.fb.group({});
    this.exercises[0].questions.forEach(control => 
      this.exerciseForm.addControl(control.id, this.fb.control(''))
    );
    return this.exerciseForm;
}

In app.component.html, make just one change (Assigning unique formcontrolname)

Replace,

formControlName="answer"

With

[formControlName]="question.id"

Forked Stackblitz Here..

Answer №2

Link the formControlName to the index value, then reference it by name in the exerciseForm

[formControlName]="'answer_' + question.id"

Access the control like this:

this.exerciseForm.controls['answer_1']

Alternatively:

this.exerciseForm.get('answer_1')

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

Unveiling the secrets of decoding a JWE token within an Angular environment

I encountered an issue while developing a JWE in .net core using EncryptingCredentials. Here is the snippet of code I used: var key = Encoding.ASCII.GetBytes(Configuration["Core:JwtSecret"]); var encryptionkey = Encoding.ASCII.GetBytes(Configurat ...

Utilize Angular Service Worker to prefetch API data efficiently (dataGroups)

I am working on an Angular website that needs to function offline. In order to achieve this, I need some data from the API, which can be considered Stale data. To handle this scenario, my approach is to first attempt to retrieve the data from the API, and ...

Utilizing functions from external modules in Angular

Recently, I created an es6 module with some exported functions and published it on npm after uploading its transpiled es5 code. Right now, I am in the process of trying to integrate this package into an Angular project that utilizes SystemJS as a module l ...

"Enhance your coding experience in VS Code with intelligent auto-completion for JavaScript files using type definitions that support import

Hey there! I've been experimenting with declaring custom types in d.ts files and using them in jsdoc annotations in JavaScript files to enable intellisense in VS Code. Let's take a look at an example: In the file types.d.ts import { Request } ...

The specified 'currency' pipe was not found during Ahead of Time compilation (AOT)

Our team recently upgraded an Angular application from version 6 to 7. The application uses the built-in currency pipe, and everything was functioning correctly when running with ng serve or building in development mode. However, problems arose when attem ...

Guide on initializing a Redux toolkit state with an array of objects or local storage using TypeScript

Currently, I am attempting to set an initial state (items) to an array of objects or retrieve the same from localStorage. However, I am encountering the following error. Type 'number' is not assignable to type '{ id: string; price: number; ...

Angular 4's customizable features for loading dynamic classes

Our application features a KeypadComponent that showcases keyboard layout based on JSON input, for example: {'Q', 'W', 'E', 'R'...}. Currently, we have approximately 100 predefined keyboard layouts. However, the pot ...

What is the best way to retrieve the chosen item within a Tabmenu component in Primeng?

I have created a simple array of MenuItem objects to populate the Tabmenu component from Primeng. Here is an example: .ts file: items = MenuItem[]; activeItem = MenuItem; //constructor, etc... ngOnInit() { this.items = [ {label: &a ...

Encountering an error when using Webpack ModuleFederationPlugin and HMR: "Undefined properties cannot be set"

Description Hey everyone! I've been experimenting with Webpack ModuleFederationPlugin using React and TypeScript in my current proof of concept. Currently, I have two applications - ChildApp which exposes a module, and a HostApp that consumes this e ...

Dynamically determine the length of an array using Typescript

Can the length of an array be determined based on a numerical variable? For example: func(1); // outputs [string] func(2); // outputs [string, string] func(5); // outputs [string, string, string, string, string] ...

Customized object property names for an array of generic object types

I am working with an object in Typescript that has a data property structured like this: type MyThing = { data: { options: { myKey: string, myValue: string }[], key: 'myKey', value: 'myValue' } } I want ...

The API request does not provide randomized results and does not show any display

I am facing an issue with a button that is supposed to fetch a random user from an API. When I retrieve all the users, the information is displayed correctly. However, when I try to select a user at random, it does not work as expected. Also, it seems to a ...

What is the best way to manage a custom child event that is triggered using this.$emit in a parent component, specifically within the <script> section of the .vue file?

In our project, we're utilizing vue and typescript, which means that our .vue files are structured very similarly to the layout outlined in this blogpost. One of our child components is emitting a custom event called changeType. I'd like to trig ...

how to share a variable across multiple ts files in an Angular project

In the home.component.ts file, I have a variable named name that I want to access globally in all files. Can anyone please suggest how can I achieve this? Below is the code snippet: app.component.html <nav aria-label="breadcrumb"> <ol class= ...

The third-party SDK no longer includes names and autocomplete functionality

I am encountering an issue where my previously working SDK environment has suddenly stopped recognizing names and providing autocomplete. I am wondering what could have caused this problem - is it related to SDK maintenance or is the SDK offline? The SDK ...

The error message "better-sqlite3 TypeError: o.default is not a constructor" indicates that

As part of my vscode extension development in typescript, webpack, and better-sqlite3, I am attempting to create a database within the C:\Users\userName\AppData\Roaming\Code\User\globalStorage\ folder. However, when ...

Tips for resolving the 'JSX is not defined no-undef' error post TypeScript 4.4.2 update

Upon upgrading to TypeScript 4.4.2 from TypeScript 3.8.2, I have encountered numerous errors such as error 'x' is not defined no-undef. For instance, one of the errors is error 'JSX' is not defined no-undef. Upon closer inspection, most ...

having difficulty accessing the value within the Angular constructor

My current issue arises when I click on a button and set a value within the button click method. Despite declaring the variable in the constructor, I am unable to retrieve that value. The code snippet below demonstrates this problem as I keep getting &apos ...

Attempt to transfer the input's value to a function within Angular using mat-select from Material design

Hi, I'm working on a project that involves sending the value of mat-select from a form. Here is my HTML: <mat-form-field class="input-class" appearance="fill"> <mat-label>Choose Partner <i class="far fa-id-card"></ ...

The table dynamically adjusts based on the JSON data

My goal is to design a table that displays a JSON-object with multiple levels. The challenge is to showcase all the data in one row, even when it shows as [object object] like the Id in the plnkr example. ResultData=[ { "First_name": "xx", ...