An effective method to start an Angular reactive form with various key values

I'm currently working on creating an Angular form with predefined key names and values that remain constant. While I have successfully built a form, the output format is not exactly what I require.

keysToChange = ['key1', 'key2', 'key3', 'key4']

export interface PatchForm {
  [x: string]: FormControl<string | null>
  date: FormControl<string | null>
}

patchForm = this.fb.group({
  keysToChange: this.fb.array<FormGroup<PatchForm>>([]),
})

  initializeForm() {
    this.keysToChange.forEach((key) => {
      const formGroup = this.fb.nonNullable.group({
        [key]: new FormControl(''),
        date: new FormControl(''),
      })
      this.patchForm.controls.keysToChange.push(formGroup)
    })
  }

I get the following output:

{
    "keysToChange": [
        {
            "key1": "",
            "date": ""
        },
        {
            "key2": "",
            "date": ""
        },
        {
            "key3": "",
            "date": ""
        },
        {
            "key4": "",
            "date": ""
        }
    ]
}

However, I need something more like this:

export interface PatchForm {
  id: FormControl<string | null>
  date: FormControl<string | null>
}

Then I would like the output to be structured as follows:

{
  "key1": {
    "id": "string",
    "date": "2024-04-03T11:23:05.499Z"
  },
  "key2": {
    "id": "string",
    "date": "2024-04-03T11:23:05.499Z"
  },
  "key3": {
    "id": "string",
    "date": "2024-04-03T11:23:05.499Z"
  },
  "key4": {
    "id": "string",
    "date": "2024-04-03T11:23:05.499Z"
  }
}

The main issue I am facing lies in creating types and initializing the form because my eslint does not allow the unsafe use of type 'any', and I am struggling to understand how to set keys for each FormGroup.

Answer №1

To start, we must create a formGroup and then add each individual control using the addControl method along with the key name and formgroup. Below is a functional example for reference, feel free to reach out if you have any questions!

import { CommonModule } from '@angular/common';
import { Component, inject } from '@angular/core';
import {
  FormBuilder,
  FormControl,
  FormGroup,
  ReactiveFormsModule,
} from '@angular/forms';
import { bootstrapApplication } from '@angular/platform-browser';
import 'zone.js';

export interface PatchForm {
  [x: string]: FormControl<string | null>;
  date: FormControl<string | null>;
}

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [ReactiveFormsModule, CommonModule],
  template: `
    <form [formGroup]="patchForm">
      <div formGroupName="keysToChange">
        <div *ngFor="let item of iterKeys; let i = index" [formGroupName]="item">
          <input type="text" formControlName="id" id="id" name="id"/>
          <input type="date" formControlName="date" id="date" name="date"/>
        </div>
      </div>
    </form>
    {{patchForm.value | json}}
  `,
})
export class App {
  keysToChange = ['key1', 'key2', 'key3', 'key4'];
  name = 'Angular';
  fb = inject(FormBuilder);
  iterKeys: Array<string> = [];

  patchForm = this.fb.group({
    keysToChange: this.fb.group({}),
  });

  ngOnInit() {
    this.initializeForm();
  }

  initializeForm() {
    this.keysToChange.forEach((key) => {
      const formGroup = this.fb.nonNullable.group({
        id: new FormControl(''),
        date: new FormControl(''),
      });
      this.patchForm.controls.keysToChange.addControl(key, formGroup);
    });
    this.iterKeys = Object.keys(this.patchForm.controls.keysToChange.controls);
  }
}

bootstrapApplication(App);

View Stackblitz Demo

Answer №2

export interface PatchForm2 {
    id: FormControl<string | null>
    date: FormControl<string | null>
  }

  keysToModify = ['keyA', 'keyB', 'keyC', 'keyD']

  formData = new FormGroup({});

  constructor() {
    this.setupForm();

    console.log(this.formData.value)
  }

  setupForm() {
    this.keysToModify.forEach((key) => {
      const _formData: FormGroup<PatchForm2> = new FormGroup({
        id: new FormControl(''),
        date: new FormControl(''),
      });

      this.formData.addControl(key, _formData)
    })
  }

result

{
    "keyA": {
        "id": "",
        "date": ""
    },
    "keyB": {
        "id": "",
        "date": ""
    },
    "keyC": {
        "id": "",
        "date": ""
    },
    "keyD": {
        "id": "",
        "date": ""
    }
}

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

Managing the ERR_NAME_NOT_RESOLVED issue

Currently, I am facing a task related to the health check endpoint where I need to receive a response from the backend or encounter a net::ERR_NAME_NOT_RESOLVED error if we are outside of a specific network. When attempting to send a request to my endpoin ...

Automatically identify the appropriate data type using a type hint mechanism

Can data be interpreted differently based on a 'type-field'? I am currently loading data from the same file with known type definitions. The current approach displays all fields, but I would like to automatically determine which type is applicab ...

Learn the process of adjusting the Time Zone in Angular2-HighCharts!

I've been struggling for a few days now trying to adjust the UTC time in an area chart using Angular2-HighCharts. The backend API is returning timestamps which I then inject into the chart, but each time it's being converted to "human time" with ...

What is the proper way to arrange dates within strings in Angular?

I'm currently facing an issue with sorting two strings. The strings in question are: "2022 | Dec (V2 2022)" "2022 | Jul (V1 2022)" Although I am attempting to sort them using localeCompare, it is not yielding the correct result. T ...

SweetAlert2 not displaying properly in Ionic6 - troubleshooting the issue

My current project is an Ionic 5 Angular project with SweetAlerts2 popups. Recently, I decided to upgrade to Ionic6 and encountered an issue where the SweetAlerts2 popups are not displaying correctly. The alert seems to only show up in the header, leaving ...

The TypeScript compiler within WebStorm recognizes the TSConfig.json file as a valid TypeScript file

When working on my TypeScript project in WebStorm, I encountered an issue where the TypeScript compiler recognized my tsconfig.json file as a TS file. Adjusting TypeScript Settings in WebStorm: https://i.sstatic.net/EyX6T.png Error Encountered: https://i ...

Issue with Angular2 not able to call POST method in CodeIgniter RESTful API resulting in 404 error

I am encountering an issue with my codeigniter restful API. While the GET method is working fine, I am unable to get the POST method to work from Angular2. this.api.post('quality/addeditquality', this.formdata).subscribe(data => { c ...

Is it possible to access the generic type that a different generic type inherits in TypeScript?

I've developed an interface specifically designed for types capable of self-converting to IDBKey: interface IDBValidKeyConvertible<TConvertedDBValidKey extends IDBValidKey> { convertToIDBValidKey: () => TConvertedDBValidKey; } My goal n ...

What is the best way to retrieve a plus sign from a URL parameter?

Is there a way to include the A+ or A- bloodGroup in a URL parameter but have it display correctly? I'm trying to send it using a link like this: Can anyone help me with this issue? I need the + sign to show up properly in the response. When I use ...

Angular: Implementing a canActivate guard to restrict redirects exclusively from a specific component

My dilemma involves restricting access to a specific component only when it is accessed through a redirect from another component. Simply entering the URL in the browser should not grant access, but if the user is redirected from a particular component, ac ...

What steps should I take to address conflicting type identifiers between Cypress and jQuery?

Currently, I am tasked with writing TypeScript end-to-end tests for an Angular 11 application. Following the recommended practices of Cypress, my test setup is encountering a conflict due to existing jQuery dependencies (3.5.1) in the app and Cypress (8.4. ...

What is the reason behind having to coerce the enum value before the object type can be properly recognized?

My object is discriminated based on the type property, which can be any value from a specified enum. I encounter an issue in TypeScript when passing a valid object to a function; it complains about mismatched types. However, coercing the enum value resolve ...

The hook from Supabase is facing issues with proper importing

This project is a Spotify clone. The issue I'm facing is related to importing the hook. The error message reads: React Hook "useSupabaseClient" is called in function "useloadArtistImage" that is neither a React function component nor a custom React H ...

Angular: Automatically update HTML content once promise is resolved

I'm facing an issue with Angular and Promises that I can't seem to figure out. Here is the code snippet from my HTML file: <div>Is Ready? {{isReady}}</div> <div *ngIf="isReady">Show this</div> <div *ngIf=&quo ...

The array is populated with elements, yet the size remains zero

In my code, I utilize an array that consists of multiple subarrays and then push objects into it. The pushing process looks like this: this.storeFilesService.base64files.filetype1.push({name: file.name, base64: str}); Once I push an object into a subarr ...

Troubleshooting tips for resolving issues with an Express Router using GET requests

I am in the process of developing a game using a MEAN stack, which requires creating an API with Node & MongoDB to store scores and utilizing this API in an Angular client. Although I have successfully set up the database and can add scores using the POST ...

The default route in Angular is always preloaded and ready to be

I currently have two routes available: home [ '' ] about [ 'about' ] Upon directly accessing the /about route in my browser, I've observed the following: The home module is preloaded even though I requested /about. The URL gets ...

Is there a way for me to retrieve the callback parameters?

Can the parameters of the callback function be accessed within the 'outer' function? function f(callback: (par1: string)=>void): void { // Is it possible to access 'par1' here? } ...

The NextJS application briefly displays a restricted route component

I need to ensure that all routes containing 'dashboard' in the URL are protected globally. Currently, when I enter '/dashboard', the components display for about a second before redirecting to /login Is there a way to redirect users to ...

Having trouble assigning the class property in Angular 5

Upon loading the page, a list of products is retrieved from an external JSON source. Each product in the list has a corresponding BUY button displayed alongside it, with the ID of the respective product assigned to the button. The intention is that when a ...