Tips for adding items to a Form Array in Angular

I am working on a project with dynamic checkboxes that retrieve data from an API. Below is the HTML file:

<form [formGroup]="form" (ngSubmit)="submit()">
  <label formArrayName="summons" *ngFor="let order of form.controls.summons.controls; let i = index">
    <input type="checkbox" [formControlName]="i">
    {{summons[i].name}}
  </label>

  <div *ngIf="!form.valid">At least one order must be selected</div>
  <br>
  <button [disabled]="!form.valid">submit</button>
</form>

Here is the TypeScript file:

interface Item {
  offenceType4: string;
  permSpeed: string;
  actSpeed: string;
  itemAttributes: ItemAttributes;
  offenceLoc: string;
  itemNo: string;
  summonDate: string;
  distCode: string;
  summonType: string;
  hbtlOffndr: string;
  itemAmount: number;
  itemAttributesCount: number;
  summonAmt: string;
  offenceType1: string;
  offenceCode1: string;
  offenceType2: string;
  offenceCode2: string;
  offenceType3: string;
  category: string;
  offenceCode3: string;
  offenceCode4: string;
  respCode: string;
}

interface ItemAttributes {
  attribute5: string;
  attribute4: string;
  attribute7: string;
  attribute6: string;
  attribute1: string;
  attribute3: string;
  attribute2: string;

}
interface RootObject {
  items: Item[];
  status: Status;
  additionalProperties: AdditionalProperties;
  metadata: Metadata;
}

export class InquiryResponseMultiselectComponent implements OnInit {
  form: FormGroup;
  summons = [];
  data: any[];

  constructor(
    private formBuilder: FormBuilder,
    private inquiryService: InquiryService
  ) {
    this.form = this.formBuilder.group({
      summons: new FormArray([], minSelectedCheckboxes(1)),
    });

     this.getSummon().subscribe(summons => {
      this.summons = summons;
      this.addCheckboxes();
    });
  }

  ngOnInit() {
    this.getSummon();
  }

  getSummon() {
    return this.inquiryService.getData().pipe(map((item: RootObject) => 
  item.items)) ;
  }

  addCheckboxes() {
    this.summons.map(i => {
    const control = new FormControl();
    const formArray = this.form.controls.summons as FormArray;
    formArray.push(control);
    });
  }

After fetching the response from the API to dynamically update my checkbox options, I encountered an error.

core.js:9110 ERROR TypeError: Cannot read property 'map' of undefined

If I don't perform mapping like this:

  addCheckboxes() {
      const control = new FormControl();
      const formArray = this.form.controls.summons as FormArray;
      formArray.push(control);
  }

The default length of the formControl will be equal to 1, which is not desired. Any guidance on how to resolve this issue would be greatly appreciated.

Answer №1

When utilizing formbuilder, there is no need to initialize the formarray using FormArray. Instead, you can make use of the formbuilder API.

   this.form = this.formBuilder.group({
      summons: this.formBuilder.array([]),
    });

For example, check out this link: https://stackblitz.com/edit/angular-boxw51.

Answer №2

When initializing the form before receiving the data, it becomes a challenge to modify something that already exists rather than creating it from scratch. Consider initializing your form within the subscription where you have a clear understanding of what elements should be included in your array.

  constructor(
    private formBuilder: FormBuilder,
    private inquiryService: InquiryService
  ) {

    this.inquiryService.getData().subscribe((receivedSummons: RootObject[]) => {
      this.summons = receivedSummons[0].data;

      let formControls = this.summons.items.map((summon, index) => {
        return new FormControl(index === 0);
      });
      this.form = this.formBuilder.group({
        summons: new FormArray(formControls),
      });
      this.addCheckboxes();
    });
  }

To prevent errors when accessing an uninitialized form, use a condition (*ngIf) at the beginning of your HTML form:

<form *ngIf="form" [formGroup]="form" (ngSubmit)="submit()">
  <label formArrayName="summons" *ngFor="let order of form.controls.summons.controls; let i = index">
    <input type="checkbox" [formControlName]="i">
    {{summons[i].name}}
  </label>

  <div *ngIf="!form.valid">At least one order must be selected</div>
  <br>
  <button [disabled]="!form.valid">submit</button>
</form>

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

Guide on incorporating arrow buttons for navigation on the left and right sides within a Primeng tab view component in Angular 8

Looking to enhance navigation tabs with left and right arrows for better support of larger tab sizes in the nav menu. I attempted using Primeng since my Angular 8 application already utilizes this library. Are there any other libraries besides Angular Ma ...

Guide to keep the loader running until the API response is retrieved in Ionic 4

I'm currently developing an app using Ionic 4 where I am retrieving data from an API. To enhance user experience, I have included a loader on the front page that shows while the data is being fetched. My goal is to keep the loader running until the d ...

Develop a versatile class for storing an array of key-value pairs (dictionary) using TypeScript

I am looking to implement a Dictionary class in my application. I have created a class with an Array of KeyValuePair to store my list. export class KeyValuePair<TKey, TVal>{ key:TKey; value:TVal; constructor(key:TKey, val:TVal){ this.key = key; ...

Trigger an event when an Angular template's *ngIf condition is met

Let's say I am using the Angular directive *ngIf to display a user object like so: <div *ngIf="user$ | async as user" class="container"> <p>{{user.name}}</p> </div> Is there a method where I can trigger some code once this ...

How can I access and modify a sub collection document in Angular Firestore?

I am facing a challenge in fetching a single document from a Firestore sub collection with the path: database/users/uid/animal/docID Although I have successfully parsed the docID from another component, I am struggling to retrieve the information to displ ...

The filename is distinct from the file already included solely by the difference in capitalization. Material UI

I have recently set up a Typescript React project and incorporated Material UI packages. However, I encountered an error in VS Code when trying to import these packages - although the application still functions properly. The error message reads: File na ...

Firebase: No user record exists for this identifier. It is possible that the user has been removed from the system

Utilizing Ionic2/Angular2 along with AngularFire2 and Firebase for user authentication during login. Upon successful registration of a user using email & password, I am able to log in with that same email & password without any issues. public fireAuth: ...

Displaying the initial element in an NgFor loop in Angular 2

Whenever I click on the "Add row" button, I dynamically generate a row of inputs and dropdowns. Upon clicking another button, the complete data is submitted and displayed in console.log as an array of objects, with each object representing a single row. C ...

Incorporate a class name within a div element in Ionic 2

When using Alert components, I want to add the class name animated zoomIn to the div next to <div class="alert-wrapper"></div> Is it possible?https://i.sstatic.net/t4mek.jpg doAlert() { let alert = Alert.create({ cssClass: &apos ...

Angular - Error: Unable to assign value to a reference or variable

I am currently working on an app built with Angular 8. app.component.html <div> <label class="form-check-label f-14"> <input type="checkbox" class="form-check-input" name="isAgree" [(ngModel)]="isAgree" #isAgree="ngModel"/> ...

The property 'value' is not recognized on the Element type

I am currently working on a project where I need to calculate the total sum of values entered in a specific column within a mat-table. The setup involves creating a table with three columns: Account Id, Account Description, and Value. Additionally, I have ...

Struggling to implement the proper authentication method with API in Ionic

Having an API for the login, but being new to Ionic is causing difficulty in creating the correct method for the login process. The service file is located here: providers/restapi/restapi.ts import { HttpClient } from '@angular/common/http'; im ...

Presenting data in various formats

I've got a JSON file with a list of data that includes months and years. I want to display all the months, but have the year only appear once in a big block area. Here's an image example: https://i.stack.imgur.com/Ps3OF.png The image demonstrates ...

Does the Rxjs timer cease functioning when the user switches to a different window?

I have encountered an issue while setting a 60-second countdown with rxjs timer on Angular 11. The countdown works properly as long as the window is kept open. However, if I switch to another tab in the same browser, the timer stops after a few seconds. Th ...

Obtain the Nodes attribute using PrimeNG

Here is the JSON output I am working with: { "data": [ { "label": "The Avengers", "data": { "name" : "The Avengers", "type" : "book"}, "expandedIcon": "fa-folder-open", "collapsedIcon": "fa-folder", "leaf": true ...

agm-circle has such a high drag sensitivity in angular 4

I have implemented an agm-circle in an agm-map within Angular 4. Everything is working as expected, however, I am experiencing an issue with the speed at which the circle moves when dragged. Is there a way to slow down this movement? Below is my code sni ...

Trying to Grasp the Concept of Angular Bootstrap AutoComplete

I am trying to make sense of this code snippet. Within the code at line 44, there is something like search = (text$: Observable) => When I hover over 'search', Intellisense indicates (property) of NgbdTypeaheadHttp.search I'm confused ...

Issue with utilizing Material Button Icon in the header of a datatable in Angular 7

I'm currently facing an issue with incorporating a refresh button into a Material Data Table on Angular 7. Strangely, instead of displaying the icon, refresh, it appears in italicized text. Below is the snippet of code causing the problem: <table ...

Tips for adjusting the width of the box on a BoxPlot chart in Apex charts

Currently, I am utilizing apexcharts(version 3.35.3) within an Angular project and I am looking to adjust the width of the box. After reviewing the documentation for apexcharts, I have not been able to find any specific option that allows me to modify the ...

When transitioning to angular 10 and removing decorators from classes, what is the best approach for dealing with a base class that is inherited by both Directives and Injectables?

During the angular 10 migration process, there is a recommendation that classes utilizing angular features should have a decorator. However, what should be done in cases where it's a base class shared by both Injectables and Directives (as it solely i ...