Create an interactive Angular form that dynamically generates groups of form elements based on data pulled from

I am currently developing an Angular application and working on creating a dynamic form using Angular.

In this project, I am attempting to divide the form into two sections: Person Name and Personal Details.

While I have successfully grouped fields for Person Name, I am facing issues with grouping fields for Personal Details.

The HTML:

<div *ngIf="form">
  <div *ngFor="let question of questions" class="form-row" [formGroup]="form">
      <ng-container *ngIf="!question.children">
        <app-question [question]="question" [form]="form"></app-question>
      </ng-container>
      <ng-container *ngIf="question.controlType === 'group' && question.children && question.children.length > 0">
        <app-dynamic-group [questions]="question.children" [form]="form.controls[question.key]" [key]="question.key" [formControlName]="question.key"></app-dynamic-group>
      </ng-container>
  </div>
</div>

JSON:

jsonData: any = [
    {
      "elementType": "group",
      "key": "person_name",
      "children": [
        {
          "elementType": "textbox",
          "class": "col-12 col-md-4 col-sm-12",
          "key": "first_name",
          "label": "First Name",
          "type": "text",
          "value": "",
          "required": true,
          "minlength": 3,
          "maxlength": 20,
          "order": 1
        },
        {
          "elementType": "textbox",
          "class": "col-12 col-md-4 col-sm-12",
          "key": "last_name",
          "label": "Last Name",
          "type": "text",
          "value": "",
          "required": true,
          "order": 2
        }
     ],
    },
        {
      "elementType": "group",
      "key": "personal_details",
      "children": [
        {
          "elementType": "textbox",
          "class": "col-12 col-md-4 col-sm-12",
          "key": "email",
          "label": "Email",
          "type": "text",
          "value": "",
          "required": true,
          "minlength": 3,
          "maxlength": 20,
          "order": 1
        },
        {
          "elementType": "textbox",
          "class": "col-12 col-md-4 col-sm-12",
          "key": "mobile",
          "label": "Mobile",
          "type": "text",
          "value": "",
          "required": true,
          "order": 2
        }
     ],
    },
  ];

The functional Stckblitz: https://stackblitz.com/edit/angular-x4a5b6-5uj52y

Currently, everything seems to be functioning correctly. While I have successfully created a group for Person Name, I am facing difficulty in displaying the input boxes for Personal Details.

The requirement is to split a single form into two parts with titles above each section.

To achieve this structured display, where only the parent title is displayed at the top of each section (e.g., "Person Name (Has First and Last Name)", "Personal Details (Has Email and Mobile)"), I need assistance on how to implement this.

I aim to achieve the following order of display:

Person Name

 -> First Name
 -> Last Name

Personal Details

 -> Email
 -> Mobile Number

If my approach so far is incorrect, I kindly request guidance on splitting the dynamic form as shown in this example.

My goal is to achieve a form layout similar to this example, but incorporating pure Angular dynamic form creation and JSON data loading.

Please assist me in creating a group for Personal Details, akin to how the Person Name group has already been created and is functional.

I have been struggling with this issue for quite some time, your help would be greatly appreciated...

Answer №1

It seems unnecessary to create an additional formGroup in this situation:

this.form = new FormGroup({main: innerForm});

You can simply utilize the formGroup obtained from your service like this:

dynamic-form.component.ts

this.form = this.qcs.toFormGroup(this.questions);

dynamic-form.component.html

<app-dynamic-group [questions]="questions" [form]="form"></app-dynamic-group>

By passing the FormGroup directly to the DynamicGroupComponent, there is no need to implement ControlValueAccessor. The form should be sufficient for dynamic form generation.

dynamic-group.component.ts

@Component({
  selector: 'app-dynamic-group',
  templateUrl: './dynamic-group.component.html'
})
export class DynamicGroupComponent {
  @Input() form: FormGroup;

  @Input() questions: QuestionBase<any>[] = [];
}

dynamic-group.component.html

<div *ngFor="let question of questions" class="form-row">
    <app-question *ngIf="!question.children" [question]="question" [form]="form"></app-question>

    <app-dynamic-group 
       *ngIf="question.controlType === 'group' && question.children && question.children.length"
       [form]="form.get(question.key)"
       [questions]="question.children">
    </app-dynamic-group>
</div>

Forked Stackblitz

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

Is it possible to toggle all parent targets in Bootstrap?

When trying to showcase my point, I believe it is best demonstrated by visiting Bootstrap documentation at https://getbootstrap.com/docs/4.0/components/collapse/ and viewing the "multiple targets section." In this section, you will find three buttons: togg ...

Subsequent modal forms do not trigger Ajax responses

I have a list of items displayed on a page, with each item having a link that opens a unique modal. Inside this modal, there is a text field for entering a username and an AJAX call to display usernames when "@" is typed (pretty cool, right?). The issue I& ...

Display the HTML/CSS layout following the JavaScript window.open action

Encountering issues with printing output in an opened window using JavaScript. I'm creating a new document through window.open and including CDN links to Bootstrap files. While everything appears fine in the opened window, when attempting to print (XP ...

Data has not been submitted to the MongoDB database

I attempted to save form data in my mongodb database (mongodb compass). However, after submitting the form, I checked the database and found that it was empty. When I clicked the sign-up button, it only displayed curly brackets. Main file - App.js co ...

Creating dynamic styles with Material-UI's useStyles

Attempting to implement the same logic using material-ui's useStyle feature <div className={'container ' + (state.unlocked ? 'containerUnlocked' : '')}> I thought it might look like this: <div className={`${clas ...

The combination of useEffect and Client component has the power to greatly

As a newcomer to React development, I've encountered a blocking error in my code that isn't being detected by Visual Studio Code. Here's the code snippet for my NavBar component: import React, { useState, useEffect } from "react"; import Ima ...

Load a Javascript file from the local server

My website is encountering a problem when trying to load a script from a localhost server. The error message displayed is PROTOCOL ERROR: https://localhost:4200/script/test.js net::ERR_SSL_PROTOCOL_ERROR Here is the code snippet causing the issue: <!DO ...

Display the image before submitting it on Shiny platform

I'm currently developing a Shiny app that enables users to upload images directly to the server. I am wondering if there is a way to display the image on the screen without going through the process of uploading it first and then receiving the rendere ...

Setting values from json_decode into respective variables

I am working on building a Restful web service for an Android application using PHP and Slim framework. Currently, I have successfully parsed JSON data but I am looking to store the individual values associated with each key in separate variables. While I ...

The stream-chat-js package is causing an Angular compile error due to the absence of an exported member named 'Client'

Encountering an issue while attempting to compile an Angular application using the Node version of Stream Chat package. ERROR in node_modules/getstream/types/getstream/index.d.ts(12,11): error TS2694: Namespace '"/Users/.../app/node_modules/stream-c ...

Evaluate the advancement of a test using a promise notification for $httpBackend

I am currently utilizing a file upload feature from https://github.com/danialfarid/angular-file-upload in my project. This library includes a progress method that is triggered when the xhr request receives the progress event. Here is an excerpt from the so ...

Using Angular: How to set the index value from a dropdown to a local variable after a button is clicked

Can someone please provide guidance on how to assign the index value (i = index) to EmployeeIndex: any; after a button click event? Your suggestions are greatly appreciated. Here is my code: HTML <select class="form-control" [(ngModel)]="EmployeeNam ...

Is there a way to maintain the second form's state when the page is refreshed using Vue.js?

I have a challenge in creating a web-app with only 2 pages. The first page requires filling out forms across two stages, but I am unable to create separate pages for this purpose. Is there a way to display two forms on one page and remain on the second for ...

Interchanging JSON and XML formats in C/C++ programming

I've been exploring various options but have yet to find a reliable set of routines for converting between JSON and XML in C or C++. While I've come across solutions in Javascript, Java, PHP, and Python, my json library is json-spirit. Currently ...

What steps should I take to fix an error in my code?

My current objective is to write a program that generates a square with dimensions of 200 pixels by 200 pixels. The square should be colored using specific RGB values: red (red value of 255), green (green value of 255), blue (blue value of 255), and magent ...

How to use Ionic 3 to automatically scroll ion-scroll content all the way to the bottom

My ion-scroll component is experiencing some challenges <ion-scroll scrollY="true" style="height: 52vh;"> {{ text }} </ion-scroll> The content inside the ion-scroll keeps expanding, exceeding the designated height. Users can manually scroll ...

How to extract a one-of-a-kind identification number from the browser using just JavaScript in a basic HTML file?

Is there a way to obtain a distinct identification number from a browser without resorting to techniques such as generating and storing a unique number in cookies or local storage, and without utilizing a server-side language? ...

Passing an array from the PHP View to a JavaScript function and plotting it

Greetings, I am currently facing the following tasks: Retrieving data from a database and saving it to an array (CHECK) Sending the array from Controller to View (CHECK) Passing that array to a JavaScript function using json_encode (CHECK) Plotting the ...

Implementing append operations in JavaScript without relying on the id attribute

Is there a way to specify the second div without assigning it an ID or using any attributes, and then perform an append operation inside it? For instance, indicating that the p element should be appended within the second div without relying on an ID or ...

Is there a way to use JavaScript to modify the position of a div element

Can we adjust the div position using CSS (absolute or relative) with JavaScript? Here's an example code snippet: <div id="podpis" style="margin-top: 2rem;"> <div class="invoice-signature"> <span><?=$xml->sanitiz ...