Building a Dynamic Form Array with Options for Selection

I am facing an issue with reactive forms and a radio button array in my project. The problem is that I can only select one package at a time instead of multiple packages. Can anyone guide me on how to enable the selection of multiple packages? You can view my demo on Stackblitz. Here's what my Form layout looks like:

https://i.sstatic.net/FiU2v.png

And here is an example of my code:

HTML
<div class="card col-8 shadow-sm">
    <div class="list-group">
        <form name="form" [formGroup]="form" (ngSubmit)="form.valid && onSubmit()">
        <div class="list-group-item flex-column align-items-start" *ngFor="let list of packages ; let i=index">
            <div class="card-body">
                <div class="d-flex justify-content-between mb-3">
                    <span class="d-flex align-items-center">
                        <h5 class="card-title pr-3 d-inline-block font-weight-bold">{{list.eventName}}</h5>
                    </span>
               </div>

                <p class="card-text">
                    {{list.eventNote}}
                </p>
                <div>
                    <span class="font-weight-bold pr-2">Attendings :</span>
                    <span class="ml-5">
                    <mat-radio-group formControlName="attendings"  aria-label="Select an option">
                        <mat-radio-button value="y">Yes</mat-radio-button>
                        <mat-radio-button value="n">No</mat-radio-button>
                      </mat-radio-group>
                    </span>
                </div>
                <div class="w-60 mt-4">
                    <div class="card  card-line col-md-12 mb-3" *ngFor="let fee of list.feeList">
                         <div class="card-body ctrl-height">
                         <input type="radio" formControlName="fee" id="{{fee.feeId}}" [value]="fee">
                         <label for="{{fee.feeId}}">
                          <span class="id-conf">{{fee.category}}</span>
                          <span class="price">{{fee.price}}</span>
                        </label>
                        </div> 
                      </div>
                </div>
            </div>
        </div>
    </form>
     </div>
     <div class="card-footer no-gutters ctrl-lr">
        <div class="card-body float-right"> 
            {{form.value | json}}
            <a (click)="submit()"  class="btn btn-primary  card-link d-inline pl-4 pr-4">Next </a>
        </div>
      </div>
  </div>

Component

packages = packages;

   form = new FormGroup({
    attendings: new FormControl,
    fee: new FormControl

   });
  submit() {
    console.log(this.form.value)
  }

Answer №1

You currently have arrays of packages within your package-list component, but you only have one FormGroup that contains attendings and fee FormControls for all these packages. As a result, any selection made overwrites the existing FormGroup.

It is recommended to utilize FormArray

Modifications in your package-list.component.ts

import { FormArray, FormControl, FormGroup } from '@angular/forms';

...

export class PackagesListComponent implements OnInit {

  packages = packages;

  // Generate an array of FormGroup
  controls = packages.map(pack => {
    return new FormGroup({
      attendings: new FormControl(),
      fee: new FormControl()
    });
  });

  // Generate a main FormGroup containing our FormArray
  // The FormArray will contain the generated FormGroups with necessary FormControls
  form = new FormGroup({
    formArray: new FormArray(this.controls)
  });

  // This getter is used in the template to retrieve the formArray
  get myFormArray() {
    return this.form.get('formArray') as FormArray;
  }

  ...


}

Modifications in your package-list.component.html

<div class="card col-8 shadow-sm">
    <div class="list-group">
        <form name="form" [formGroup]="form" (ngSubmit)="form.valid && submit()">
        <div class="list-group-item flex-column align-items-start" *ngFor="let list of packages; let i = index">
            <div class="card-body">
                <div class="d-flex justify-content-between mb-3">
                <span class="d-flex align-items-center">
                <h5 class="card-title pr-3 d-inline-block font-weight-bold">{{list.eventName}}</h5>
                </span>
               </div>

                <p class="card-text">
                    {{list.eventNote}}
                </p>
                <div>
                    <span class="font-weight-bold pr-2">Attendings :</span>
                    <span class="ml-5">
                    <mat-radio-group [formControl]="myFormArray.at(i).get('attendings')"  aria-label="Select an option">
                        <mat-radio-button value="y">Yes</mat-radio-button>
                        <mat-radio-button value="n">No</mat-radio-button>
                      </mat-radio-group>
                    </span>
                </div>
                <div class="w-60 mt-4">
                    <div class="card  card-line col-md-12 mb-3" *ngFor="let fee of list.feeList">
                         <div class="card-body ctrl-height">
                         <input type="radio" [formControl]="myFormArray.at(i).get('fee')" id="{{fee.feeId}}" [value]="fee">
                         <label for="{{fee.feeId}}">
                          <span class="id-conf">{{fee.category}}</span>
                          <span class="price">{{fee.price}}</span>
                        </label>
                        </div> 
                      </div>
                </div>
            </div>
        </div>
    </form>
     </div>
     <div class="card-footer no-gutters ctrl-lr">
        <div class="card-body float-right"> 
            {{form.value | json}}
            <a (click)="submit()"  class="btn btn-primary  card-link d-inline pl-4 pr-4">Next </a>
        </div>
      </div>
  </div>

The following changes have been made:

  1. Updated the *ngFor in line number 4:
    <div class="list-group-item flex-column align-items-start" *ngFor="let list of packages; let i = index">
  2. Modified line number 18:
    <mat-radio-group [formControl]="myFormArray.at(i).get('attendings')"  aria-label="Select an option">
  3. Adjusted line number 27:
    <input type="radio" [formControl]="myFormArray.at(i).get('fee')" id="{{fee.feeId}}" [value]="fee">

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

Tips for passing parameters to an Angular compilation process?

Typically, Angular gets its environment settings from environment.[env].ts files during build time. However, I find myself in a situation where I need to be able to override those settings based on arbitrary parameters like apiUrl or connectionString that ...

Pressing the button within an Angular Material Card will activate the card's own click event

<mat-card *ngFor="let p of products" (click)="viewProduct(p)"> <mat-card-actions> <button mat-stroked-button (click)="addProductToCart(p)">Add to cart</button> </mat-card-actions> ...

What is the best way to find the beginning and end of the week using Moment.js?

Is there a way to retrieve the date of the first day of the week and the date of the last day of the week using Moment.js? I am looking to fetch the dates from the start of the week until the end of the current week based on the current day in Moment.js. ...

Filtering multiple values from a JSON array in Angular 15, separated by commas

Currently, I am implementing Angular 15 in my project. While I am able to filter a single value from the search box, my goal is to filter multiple values separated by commas. Any assistance on achieving this would be greatly appreciated. FilterPipe impor ...

Encountered a challenge in Angular 2.4 when attempting to import a feature module from another project into the main project

I currently have two distinct projects, one serving as the main project and the other as a shared project. Within the shared project, I have developed a feature module known as NavBar. The intention behind separating these projects is to facilitate the re ...

Trouble configuring a React TypeScript router has arisen

Recently, I have successfully set up multiple routers in TypeScript. However, I am facing challenges in implementing the same in a new project for some unknown reason. import React from 'react'; import Container from './Components/Containers ...

Tips for exporting a React Component without using ownProps in a redux setup with TypeScript

I'm currently working on a project using typescript with react-redux. In one of my components, I am not receiving any "OwnProp" from the parent component but instead, I need to access a prop from the redux state. The Parent Component is throwing an er ...

The imported package is not functioning properly within the project

I've recently developed a Typescript Package and I want to test it in an application before publishing it on NPM. The main file (index.ts) of the package is structured like this => import Builder from './core/builder'; export default ...

Angular 4 is having trouble retrieving the JSON response

When I attempt to log errors in a specific scenario and use error, the following error message is displayed: { "errors" : [ { "entity" : "Movement", "property" : "direction", "invalidValue" : null, "message" : "Il campo non può essere v ...

Angular - Bootstrap modal displays as a standalone element rather than a dialog box

Currently working on my initial Angular project, I am attempting to incorporate a dialog that prompts for confirmation before deleting an item. Utilizing ng-bootstrap, I referred to the examples in the documentation as my starting reference. The issue I a ...

What design should be used for a class with two interconnected attributes?

I am looking to develop a customizable macro item that can be edited by the user. Each macro item will have a defined type and event value. There are three types of items: pressKey, releaseKey, and delayInMs. For pressKeyEvent and releaseKeyEvent, I wan ...

Why do all the values in my table turn into input boxes when I click the edit button?

When working with my HTML, I am using ngFor to iterate through a list of items and display them in a table. However, when I try to edit an item by clicking on it, the input box opens but all the table rows display the same value. <tr *ngFor="let item o ...

Optimizing Your Approach for Rolling Out Test and Development Application Versions on Google Compute Platform

Google Computing Platform I currently have an Angular (2) application and a Node.js middleware (Loopback) running as Services in an App Engine within my project. We are using a Compute Engine to run PostgreSQL for our database in the same project. Our Go ...

The module 'react-bootstrap' cannot be located within a module that is not commonjs

I am encountering an issue where I am unable to use React Bootstrap with a module other than commonjs in a project that utilizes React with Typescript. To start, I install the react-bootstrap package: $ npm i react-bootstrap Following installation, I pro ...

Incorporate an image into your webpage with the Fetch API by specifying the image link - JavaScript

I've been attempting to retrieve an image using the imageLink provided by the backend server. fetchImage(imageLink) { let result; const url = `https://company.com/internal/document/download?ID=${imageLink}`; const proxyurl = 'https:/ ...

How to modify the background color within the mat-menu-panel

Incorporating angular 9 and less into my current project, I have encountered an issue with a mat-menu-panel where my mat-menu-item is located. While I have successfully changed the color of my mat-menu-item, I am now faced with the challenge of changing th ...

Tips for effectively managing asynchronous tasks

I keep getting different numbers every time my code runs. Can you tell me if I'm doing this the right way? Here's the code: export class GetPlanetsService { url='https://swapi.co/api/planets/?page='; planets:Planet[]=[]; headers: ...

"Troubleshooting: Child Component Not Reflecting Changes in UI Despite Using Angular

My child component is designed to display a table based on a list provided through @Input(). The data is fetched via http, but the UI (child component) does not update unless I hover over the screen. I've seen suggestions about implementing ngOnChange ...

Turning an arrayList.toString() back into a tangible ArrayList

I recently encountered a challenge in my software project where I had to save an ArrayList as a String in SQLite due to the absence of an Array data type. Now the time has come to use my array again and I need to convert it back to an ArrayList. Can anyone ...