Develop interactive form fields and implement data validation using Angular framework

I have a unique sample object that needs to be transformed into form controls:

[
    {
        "labelName": "Full Name",
        "inputType": "textbox",
        "inputValues": "",
        "mandatory": "yes"
    },
    {
        "labelName": "Email Address",
        "inputType": "textbox",
        "inputValues": "",
        "mandatory": "yes"
    },
    {
        "labelName": "Address 2",
        "inputType": "textarea",
        "inputValues": null,
        "mandatory": "yes"
    },
    {
        "labelName": "City",
        "inputType": "dropdown",
        "inputValues": null,
        "mandatory": "no"
    }
]

In order to create the form controls, I need to generate them based on the given object. Below is the code snippet for implementing this in TypeScript and HTML:

ts:

FormGroup: FormGroup;
 this.fieldsData.forEach((ele, i) => {
 form[ele?.labelName]=new FormControl('',[Validators.required]);
 });
 this.FormGroup=new FormGroup(form);

HTML:

 <form [formGroup]="FormGroup">
        <div *ngFor="let data of fieldsData">
        <label>{{data.labelName}} </label>
        <input type="text" formControlName="{{data.labelName}}">
        </div>
        <button class="btn-submit" type="button" [disabled]="!FormGroup.valid" style="margin-top: 20px" (click)="SubmitDemo()">
            Submit
        </button>
 </form>

The challenge lies in applying validation based on the mandatory key from the object. If it is set to "yes", then validation should be applied. Additionally, if the input type is 'textbox', it should be bound with an input type='text', or if it is a dropdown, it should be bound as a dropdown control.

If you have any solutions, I would greatly appreciate it. Thank you!

Answer №1

Utilizing the ngSwitch directive in HTML allows for dynamic switching between different input types.

We can also use a ternary condition to determine if a field is mandatory based on a certain condition.

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

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CommonModule, ReactiveFormsModule],
  template: `
    <form [formGroup]="FormGroup">
            <div *ngFor="let data of fieldsData">
            <ng-container [ngSwitch]="data.inputType">
              <ng-container *ngSwitchCase="'dropdown'">
                <select name="cars" id="cars">
                  <option value="volvo">Volvo</option>
                  <option value="saab">Saab</option>
                  <option value="mercedes">Mercedes</option>
                  <option value="audi">Audi</option>
                </select>
              </ng-container>
              <ng-container *ngSwitchCase="'textbox'"><textarea [formControlName]="data.labelName"></textarea></ng-container>
              <ng-container *ngSwitchDefault><input type="text" [formControlName]="data.labelName"></ng-container>
            </ng-container>
            <label>{{data.labelName}} </label>
            
            </div>
            <button class="btn-submit" type="button" [disabled]="!FormGroup.valid" style="margin-top: 20px" (click)="SubmitDemo()">
                Submit
            </button>
    </form>
  `,
})
export class App {
  fieldsData = [
    {
      labelName: 'Name',
      inputType: 'textbox',
      inputValues: '',
      mandatory: 'yes',
    },
    {
      labelName: 'Email',
      inputType: 'textbox',
      inputValues: '',
      mandatory: 'yes',
    },
    {
      labelName: 'address 2',
      inputType: 'textarea',
      inputValues: null,
      mandatory: 'yes',
    },
    {
      labelName: 'City',
      inputType: 'dropdown',
      inputValues: null,
      mandatory: 'no',
    },
  ];
  FormGroup!: FormGroup;

  ngOnInit() {
    const form: any = {};
    this.fieldsData.forEach((ele, i) => {
      const validators = ele?.mandatory === 'yes' ? [Validators.required] : [];
      form[ele?.labelName] = new FormControl('', validators);
    });
    this.FormGroup = new FormGroup(form);
  }

  SubmitDemo() {}
}

bootstrapApplication(App);

Check out the Stackblitz Demo here

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

Generating a font file using webpack in the monaco-editor package

We are currently in the process of integrating a new package into our project that has a dependency on the monaco-editor module. Let me provide you with some details about our project: We have ejected from the create-react-app project Our project is writ ...

Encountering a problem when attempting to iterate through Observable Objects in Angular 2

I've hit a roadblock trying to iterate through the observable object in my users service. The error thrown by Chrome's console is: error_handler.js:47 EXCEPTION: undefined is not a function Below is the code causing the issue: users.compone ...

What is causing elements like divs, paragraphs, or text not to display within an ion-item after an ion-input is added?

I am currently working on validating a simple form and everything seems to be functioning properly. However, I have encountered an issue with displaying text messages within an ionic 3 list item. The ion-item consists of an ion-input element. When I place ...

What methods can be implemented to ensure ComponentOverride's universality?

These type definitions for markdown-to-jsx don't seem to be generic enough, causing issues like the one mentioned below. For more details, refer to Why is type SFC<AnchorProps> not assignable to type SFC<{}>? /Users/sunknudsen/Sites/sunk ...

In Angular, components can be appended to the page instead of replacing the entire page when using router-out

After exploring all related inquiries and their accepted solutions on stackoverflow, I found that none of them worked for me. My current Angular version is 8.1.3. The issue I am facing is that when I click on a routerLink, my component gets appended to th ...

determine the total number of months within a specific duration

I need help with calculating the number of months between two dates, inclusive of both extremes. I have attempted the following code: var duration : moment.Duration; const contractStartMoment = moment(contractStart); //contractStart=01.05.2021 const ...

What is the alternative method for removing a property from an object in Typescript without triggering the 'delete' operator must be optional error?

After researching how to delete a property from an object, I came across this helpful thread on Stack Overflow. The recommended method is to use the delete keyword. So, I attempted it like this: const eventData = {...myEvent}; delete eventData.coordinate; ...

retrieve all users from the mongodb database

How can I modify this function to retrieve all users? I am currently in the process of learning async await and struggling with understanding how to access the request body. Here's my function: export const get: Operation = async ( req: express.Req ...

Tips for implementing a personalized Circuit Breaker in Node.js that monitors request volume

Currently, I am exploring the most effective way to implement a circuit breaker based on the number of requests served in a Typescript/express application rather than fail percentage. Given that the application is expected to accommodate a large volume of ...

When running ng serve, I encountered the following error message: "ERROR in Error: Internal Error: The name element has already been defined within the scope as [object Object]."

Details of Angular CLI and Node environment: - Angular CLI: 10.0.4 - Node: 12.13.0 - OS: linux x64 - Angular: 10.0.7 - Ivy Workspace: Yes List of Packages and Versions: - @angular-devkit/architect: 0.1000.4 - @angular-devkit/build-angular: 0 ...

Ways to display autocomplete suggestions when an input field is in focus

In my angular6 application using the latest angular-material, I have implemented an auto-complete feature using the component mat-autocomplete with a mat-input. The goal is to display all available auto-complete options when the user focuses on the input ...

Exporting a single value using both default and named exports simultaneously (Circular Dependency)

Recently, I was involved in a TypeScript project that utilized passport-auth0. To ensure proper typing, I added the DefinitelyTyped declaration file for @types/passport-auth0. When importing the Strategy as a named import from passport-auth0, everything f ...

Loop through an array using NgFor directive in Angular

I am facing a challenge where I have an object in my front-end application that needs to be iterated over using ngFor. The response received from the backend is structured as follows: @Component({ selector: 'docker-logs', templateUrl: ' ...

Is it possible to retrieve 2 arguments within a function in a non-sequential manner?

Let's say there is a function with arguments A, B, C, D, and E. Function(A, B, C, D, E) However, not all arguments are needed all the time. For instance, only A and C are needed in some cases. Currently, I would have to call the function like this: Fu ...

Using a class field to handle undefined status in Angular

The issue at hand involves displaying fields of a class in an html view or console. Here is my configuration: export class UserDataService { constructor( private http:HttpClient ) { } executeHelloUserBeanService(){ return this.http.get<U ...

What is the best way to retrieve an item from an array?

I have an array containing multiple records and I need to extract just one record from it using its id as an object. However, the result I'm getting is an array with that single record. Is there a way to resolve this issue? Result: [{…}] 0: {id ...

Concealing scrollbar while transitioning with Angular Animation

I could use some assistance with hiding the scrollbar during a transition. trigger("routeFadeState", [ transition(":enter", [ style({ transform: "translateY(-100vh)" }), animate("1000ms ease-out") ]), transition(":leave", a ...

The issue with Angular routing lies in the component content not displaying as expected

To showcase my project, I've created a demo on StackBlitz. I successfully implemented routing in my Angular application. You can find the code on StackBlitz. The sample consists of two components: AppComponent LoginComponent By default, when the ...

I've encountered an issue where my React website functions correctly on the development server but not on the live website. Where should I start investigating to find the cause of this discrepancy?

I am trying to embed a Datawrapper map using the following code: import InnerHTML from 'dangerously-set-html-content' export function Map1(){ const htmlFile = `<div style="min-height: 374px"> <script type="text ...

Sharing data between services in Angular 2In Angular 2, learn

I currently have a setup consisting of two components linked to 2 services. The first one being a ProductComponent: @Component({ selector: 'app-product', templateUrl: './product.component.html', styleUrls: ['./product.compon ...