How Can I Build a Dynamic Field Form Builder in Angular 4?

While working with dynamic JSON data, I needed to create fields dynamically. For instance, if my JSON array contains 3 values, I would generate 3 input checkboxes dynamically as shown below:

<ng-template ngFor let-numberOfRow [ngForOf]="numberOfRows">
   <mat-checkbox [formControlName]="numberOfRow.row" [value]="numberOfRow.row" [name]="numberOfRow.row">All</mat-checkbox>
</ng-template>

Currently, I am facing difficulties in creating a formBuilder for these fields. Can anyone guide me on how to declare formbuilder for dynamic fields?

public ngOnInit() {
   this.myForm= this.fb.group(this.formFields);
}
public formFields() {
    let empArr = [];
    for (let val of this.myArrayList) {
        empArr.push(val + ": ''");
    }
    let allFields = '{' + empArr.join(',') + '}';
    return allFields;
}

The function above (formFields) will return a string in the format

{ allRow: '', firstRow: '', secondRow: '', thirdRow: '' }
.

Instead of statically declaring the form fields like

this.myForm= this.fb.group({ allRow: '', firstRow: '', secondRow: '', thirdRow: '' });
, I am looking for a way to declare them dynamically.

Answer №1

To achieve this, start by constructing the FormControl programmatically using the control method from the FormBuilder. After that, utilize the addControl method found in FormGroup. Here's an example:

this.myForm.addControl('controlName', 
   this.fb.control({ disabled: false, value: controlValue }, validators, asyncValidators));

Next, you have to connect it using the FormControlDirective, not the FormControlName, since the control has already been created. The connection will appear as follows:

<mat-checkbox [formControl]="myForm.controls['controlName']" [value]="numberOfRow.row" [name]="numberOfRow.row">All</mat-checkbox>

Answer №2

According to @charlietfl, the issue was that I was sending string data instead of an object. Now, I have updated it to send as an object like in the code below and it is functioning correctly.

public ngOnInit() {
    this.myForm= this.fb.group(this.formFields());
 }
 public formFields() {
     let empObj = {};
     for (let value of this.myArrayList) {
         empObj[value] = '';
     }
     return empObj;
 }

So, the method above, formField, created an object like

{ allRow: '', firstRow: '', secondRow: '', thirdRow: '' }
, which resolved the issue. Thank you to everyone who helped :)

Answer №3

Example of using formBuilder to build a dynamic form:

component.ts

  form: FormGroup;

  constructor(
    private fb: FormBuilder
  ) { }

  ngOnInit() {
    this.form = this.fb.group({
      dropOffAddress : ['', Validators.required]
    })

  }

  addInput() {
    this.form.addControl(`input-${Object.keys(this.form.value).length}`, new FormControl('', [Validators.required]))
  }

  removeInput(key: string) {
    this.form.removeControl(key)

  }

component.html

<form [formGroup]="form" *ngIf="show">
  <ng-container *ngFor="let f of form.controls | keyvalue">
    <mat-form-field appearance="outline" class="w-100" color="primary">
      <mat-label>Label of Input</mat-label>
      <mat-icon (click)="addInput()" color="accent" matPrefix>add</mat-icon>
      <input type="text" [formControlName]="f.key" [name]="f.key" autofocus matInput placeholder="Enter an address">
      <mat-icon (click)="removeInput(f.key)" matSuffix>remove</mat-icon>
      <mat-error *ngIf="form.invalid">Please fill out the field</mat-error>
    </mat-form-field>
  </ng-container>
</form>

Answer №4

I organize a list containing the names of fields in a json object, alongside an array holding the form controls. Subsequently, I loop through the field names to generate checkboxes for the form.

JavaScript file:

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

export class SomeComponent
{
  form!: FormGroup;
  fieldNames: string[];
  formControls: any;

  constructor(
    private formBuilder: FormBuilder,
  )
  {
      const someJsonObject = {env: "Dev", name: "SRV", ver: "21.1" };
      this.fieldNames= [];
      this.formControls= {};

      Object.keys(someJsonObject).forEach(currentFieldName => {
        // adding the current field name to the fieldNames array
        this.fieldNames.push(currentFieldName);

        // creating a boolean formControl for each field
        this.formControls[currentFieldName] = [true];
      });
            
      // incorporating formControls into the form
      this.form = this.formBuilder.group(this.formControls);
  }
}

HTML Template file:

<form [formGroup]="form">
    <ng-container *ngFor="let currentFormControl of fieldNames">
        <div><mat-checkbox formControlName="{{ currentFormControl }}">{{ currentFormControl }}</mat-checkbox></div>
    </ng-container>
</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

Utilizing symbols as a keyof type: A simple guide

Let's consider the following: type Bar = keyof Collection<string> In this scenario, Bar denotes the type of keys present in the Collection object, such as insert or remove: const x: Bar = 'insert'; ✅ But wait, the Collection also c ...

Encountering an issue with NextJS 13 when utilizing the vectorstore recommended by Langchain, specifically receiving an error message stating that HNSWLib

Currently, I am building an application utilizing Langchain and OpenAI for assistance. My approach involves loading data using JSONLoader and intending to save it in a vectorstore. This way, I can provide specific answers to user queries based on the store ...

Displaying a portion of the chart's key in a Highcharts BarChart

I need assistance displaying a partial legend (such as min, medium, max) for the X and Y axes, along with a horizontal dashed line at the medium point of the Y axis in a HighCharts BarChart. The graph is compact on the screen, serving as a summary of multi ...

Develop a flexible axios client

I have a basic axios client setup like this: import axios from "axios"; const httpClient = axios.create({ baseURL: "https://localhost:7254/test", }); httpClient.interceptors.request.use( (config) => config, (error) => Prom ...

The error message states that the argument type '(src: Observable<any>) => Observable<any>' cannot be assigned to a parameter of type 'OperatorFunction<Object, any>'

Encountering a typescript error when trying to start the app. Not sure where I'm going wrong. It seems like it could be an issue with the rxjs version, but struggling to find the right solution. Seeing incompatible types on my system and not getting r ...

Getting pictures dynamically from the backend with unspecified file types

Greetings to my fellow Stackoverflow-Users, Lately, I was tasked with the requirement of loading images dynamically from the backend into my application. Up until now, it was always assumed that we would only be dealing with SVG images since there was no ...

Is it possible to implement lazy loading for data in TypeScript classes?

Looking to optimize my Angular application's data structure when consuming a RESTful API. My goal is to only load necessary data from the server on demand. For instance, if I have a collection of Building objects each with a set of tenant IDs in an a ...

TypeScript - Variable is inferred to have type 'any' in certain locations where its type cannot be accurately determined

I'm attempting to generate an MD5 hash from the content of an uploaded file. I am trying to set a global declaration to be used within functions, but I encounter an error when trying to utilize it: The error message states - Variable 'hasher&apos ...

Library for Typescript on npm

My project involves a collection of base classes in TypeScript. Within a web application built with React and written in TypeScript, I am looking to integrate a library called 'Plain Old TypeScript objects', which defines all the data types. Let& ...

Creating composite type guards - passing down properties from the type guard to the calling function

type Bird = { fly: () => "fly" }; type Insect = { annoy: () => "annoy" }; type Dog = { beTheBest: () => "dogdogdog" }; type Animal = Bird | Insect | Dog; const isBird = (animal: Animal): animal is Bird => { if ...

Can the automatic casting feature of TypeScript be turned off when dealing with fields that have identical names?

Imagine you have a class defined as follows: Class Flower { public readonly color: string; public readonly type: string; constructor(color: string, type: string) { this.color = color; this.type = type; } Now, let's introduce anoth ...

Using templateUrl from a remote server in Angular 2 can be achieved by specifying the complete URL

My file contains the following component with a remote URL: @Component({ templateUrl: '/mobilesiteapp/template/?path=pages/tabs' }) export class TabsPage { } Unfortunately, when compiling, I encountered this error message: [13:28:50] Error ...

Having trouble retrieving information from Node.js service in AngularJS 2

I am currently expanding my knowledge of Angular and attempting to retrieve data from a node js service using Angular 2 services. When I access the node js services directly from the browser, I can see the results. However, when I attempt to fetch the dat ...

Utilize string values as identifiers in type declarations

My Props type declaration currently looks like this: type Props<FormData> = { formData: FormData, sectionNme: keyof FormData, name: string } However, I am trying to modify it to look more like the following: type Props<FormData> = ...

What is the best way to dynamically update styleUrls or style properties in Angular?

One of my goals is to give users the ability to customize colors and certain styles within my Angular application. I am thinking about creating a structure like this: Structure: component-one   folder-with-css-files     style-for-component-1-fo ...

TS2531: Nullability detected in object when using .match() method

I'm encountering a linting error on fileNameMatches[0] in the following code snippet. Strangely, the error doesn't appear on the Boolean() check. Even if I remove that check, the issue remains unresolved. Can anyone suggest a solution? protected ...

Updating the date format of [(ngModel)] with the ngx-datepicker library

One of the challenges I'm facing is dealing with a web form that captures date of birth. To accomplish this, I'm utilizing the ngx-bootstrap version 2.0.2 datepicker module. The issue I encounter lies in the fact that my API only accepts date val ...

What is the best way to make an Angular Material checkbox respond to a programmatic change in value within a reactive form?

I have implemented a dynamic angular form that allows users to add rows using a button. I am currently working on adding functionality to select all rows. Each row includes a checkbox that toggles the value in the object between T and F. If all checkboxes ...

The child component stays consistent across all Angular routing configurations

Currently diving into Angular routing, I've added two routerLinks to the parent component. It appears that routing is set up correctly, but for some reason the page remains unchanged. Parent Child const childrenRoutes: Routes =[ {path: 'overvi ...

Using Typescript to iterate through an array of objects and modifying their keys using the forEach method

I have an object called 'task' in my code: const task = ref<Task>({ name: '', description: '', type: undefined, level: 'tactic', participants: undefined, stages: undefined, }); export interface Tas ...