Creating nested forms in Angular5 allows for complex data structures to be

I am currently exploring Angular and attempting to create dynamic forms (forms within forms).

The goal is to achieve the following:

https://i.sstatic.net/IaoJ4.png

Upon clicking the plus button, the sub-dropdown section should be added. Additionally, clicking on Add another Mapping should display a single box.

Here is my HTML file:

<div class="tab-pane" id="tab_3">
   <form [formGroup]="attrForm" novalidate (ngSubmit)="save(attrForm)">
      <div formArrayName="schemaAttr">
        <div *ngFor="let address of attrForm.controls.schemaAttr.controls; let i=index" class="panel panel-default">
          <div class="panel-heading">
            <span>Schemas {{i + 1}}</span>
            <span class="glyphicon glyphicon-remove pull-right" *ngIf="attrForm.controls.schemaAttr.controls.length > 1" (click)="removeschmeAttr(i)"></span>
          </div>

          <div class="panel-body" [formGroupName]="i">
            <div class="form-group col-xs-3">
            <ng-select [items]="configuredSchema" [closeOnSelect]="true"  bindLabel="name" placeholder="Choose a schema" (change)="onChange($event)" [(ngModel)]="selectedschema1">
            </ng-select>   
            </div>

            <div class="form-group col-xs-3">
              <ng-select [items]="configuredSchema" [closeOnSelect]="true"  bindLabel="name" placeholder="Choose a schema" (change)="onChange2($event)" [(ngModel)]="selectedschema2">
            </ng-select>
            </div>
          </div>

          <div class="panel-body" [formGroupName]="i">
            <form [formGroup]="addattrForm" novalidate>
              <div formArrayName="addAttr">
                <div *ngFor="let attribute of addattrForm.controls.addAttr.controls; let i=index" class="row">
                  <div class="form-group col-xs-3 col-md-6 col-lg-3">
                    <select [(ngModel)] ="selectedattribute1">
                     <option *ngFor="let attribute of attributes1" value={{attribute}} >
                        {{attribute}}
                      </option>
                    </select>
                  </div>

                  <div class="form-group col-xs-3 col-md-6 col-lg-3">
                    <select [(ngModel)] ="selectedattribute2" >
                     <option *ngFor="let attribute of attributes2" value={{attribute}} >
                        {{attribute}}
                      </option>
                    </select>
                  </div>

                  <div class="margin-20">
                    <a (click)="addAttr()" style="cursor: default">
                    +
                    </a>
                  </div>
                </div>
              </div>
            </form>                
          </div>

      <div class="margin-20">
        <a (click)="addschmeAttr(addattrForm)" style="cursor: default">
         Map Another schema +
        </a>
      </div>
    </div>
  </div>

      <div class="margin-20">
        <button type="submit" class="btn btn-primary pull-right" [disabled]="!attrForm.valid">Submit</button>
      </div>
  </form>

However, the desired output is not achieved. Clicking on Add Another Mapping results in the previously mapped dropdown appearing as an empty sub-dropdown. Any suggestions for better ideas to accomplish this?

Answer №1

I couldn't quite grasp your vision for the additional button in your sub-dropdown menu. However, when it comes to adding another mapping:

//Within your HTML
<div class="box" *ngFor="let array of myArray">
  <p>
    <label for="firsName">First Name:</label>
    <input type="textarea"/>
  </p>
  <p>
    <label for="firsName">Second Name:</label>
    <input type="textarea"/></p>
  <p>
    <label for="firsName">Last Name:</label>
    <input type="textarea"/>
  </p>
</div>

//Adapt the fields as needed.

<button (click)="addMoreBox()">Add More</button>
<button (click)="removeBox()">Delete Box</button>

// Within your controller/Typescript.
  myArray = ['122'];


  addMoreBox() {
    this.myArray.push('something got push');
  }

  removeBox() {
    this.myArray.pop();
  }

The main concept here is the utilization of *ngFor.

IMPORTANT

In the example provided, I simply push a string into the array. In your scenario, you should consider inserting pertinent information to monitor mapping effectively.

Feel free to experiment further here.

Answer №2

Although I strive to provide a more detailed response, I must admit that this project already does an excellent job: https://stackblitz.com/edit/deep-nested-reactive-form?file=app%2Fapp.component.html

I recommend following this fantastic example created by https://stackblitz.com/@rahulrsingh09. It is presented in a straightforward and easy-to-understand manner.

This serves as an excellent demonstration of nested forms and was instrumental in my ability to create dynamic and nested forms myself back then.

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

Error encountered: JSON.parse failed due to unexpected input at position 281

I've been struggling to find a solution, as my searches always turn up irrelevant answers. I hope someone can help me out with this issue. Thank you in advance for your assistance. TypeError: JSON.parse Error: Unexpected token at position:281 imp ...

Exploring Angular's Pipe Asset Library

I am currently developing an Angular 4 Pipe that will provide support for internationalization. My goal is to create an npm module so that other developers can benefit from this pipe as well. The pipe will utilize JSON data that developers will place in fi ...

Internet Explorer 11 fails to interpret the attribute attr.xlink:href

I am a beginner in Angular 2 and I'm working on creating an icon component. The code I have below works perfectly in Chrome and Firefox, but unfortunately, it's not functioning in Internet Explorer 11. Here is what my component looks like: @Com ...

The significance of zone.js and rxjs within the context of Angular 2

As a newcomer to Angular2, I recently learned about zone.js and rxjs. I'm curious to know if they both serve the same purpose for handling asynchronous tasks, or if each has its own specific role. Can someone explain to me the exact reasons why zone.j ...

Fixed-sized array containing union parameters

One of my programming utilities allows me to create a statically sized array: export type StaticArray<T, L extends number, R extends any[] = []> = R extends { length: L; } ? R : StaticArray<T, L, [...R, T]>; To verify its functionality, ...

How can I utilize a CDN for JavaScript libraries in Gulp?

As a newcomer to AngularJS and Gulp, I recently encountered an example where certain libraries are copied by Gulp from the 'node_modules' folder into a 'js/lib/angular2' directory: gulp.task('libs', function() { return gulp. ...

Develop a carousel component using Vue.js

I'm currently working on a dashboard that needs to display cards, but I'm running into an issue. I want only four cards visible at a time, and when you click the arrow, it should move just one step to the next card. For example, if cards 1-4 are ...

Can values be sent through an URL using a checkbox form?

Hey there, I have a question about a checkbox form. Is it possible to set up the URL like this? Here is the code for my checkbox form: <form action="c.php" method="get"> <fieldset> <legend>Filter Categories</legend> < ...

JavaScript library experiencing import issues with Typescript custom type

Working on a Vue project with TypeScript, I encountered an issue when importing a custom type created for the vue-numeral-filter package. The error message received is as follows: ERROR in /Users/bmartins/Development/app-invest/src/main.ts(14,30): 14:30 ...

Encountering a TypeScript Issue When Implementing an Interface

Compiler Error- Issue with 'MessageBus' Class: Property 'dispatch' is missing in the implementation of interface 'IMessageBus'. IMessageBus Interface- export interface IMessageBus { dispatch: (eventName: string, info?: ...

Display the JSX element only if the other element is empty

My webpage has the following structure: export default function MyBidPage() { return ( <div className="children:mb-4"> <AskToQualifyForm /> <CreateBidSection /> <DocumentsSection /> <AboutB ...

Leverage the power of mathematical functions within Angular to convert numbers into integers

In my Angular 7 Typescript class, I have the following setup: export class Paging { itemCount: number; pageCount: number; pageNumber: number; pageSize: number; constructor(pageNumber: number, pageSize: number, itemCount: number) { thi ...

How to submit a text input form using cURL

How do I create a form with a textarea for posting? <form method="post" action="/user/test/shoutbox/add" id="shoutPost" class="clearit"> <input name="formtoken" type="hidden" value="852f8fde54190fa5f9aa47172d492f829c1b"/> <input type="hidde ...

What is the best way to access Passport.js user information on the client side?

Currently, my application utilizes Angular2 on the front-end, which is served by a separate backend server running express. This back-end server also uses passport.js for Google Oauth authentication. Once a user is authenticated through Passport (using Go ...

Angular 4 RXJS Observable .interval() Fails to Execute in the Background

I have implemented a basic timer observable in my application that works fine. However, I noticed that when the tab is not active, the timer stops until I switch back to it. public timer = Observable .interval(100) Is there a way to keep the observable ...

How do I implement data range filtering in Typescript?

Seeking assistance with filtering data by date range and forwarding the results to the client. The objective is to extract tickets created within specific dates, but I keep encountering a console error which is proving challenging to resolve. var befor ...

Adjusting the resolution of a video on repeat

I am attempting to reduce the resolution of a video to below 500x500 without compromising its quality. My approach is to decrease the resolution by 75% in a loop until it reaches the desired dimensions. While this seems simple in theory, I am struggling to ...

The function record.factory does not exist

Here is the code for the AppComponent: import { Component, OnInit } from '@angular/core'; import { APICommunicationService } from './api-comm/api-communication.service'; import { Observer } from 'rxjs'; @Component({ sel ...

Ways to decrease the node_module size within an Angular application and how to efficiently load Node_Modules directly from the index.html or the root

Looking to decrease the size of node_module (currently 605MB) and load Node_Modules from index.html or application root. Using Angular 5 with node 8.9.4 Various solutions have been attempted but without the desired outcome, npm install --production Git ...

The element 'router-outlet' in Angular 9.0 is not recognized within a lazily loaded module

My attempt at adding a new lazyloaded module to the app component is running into an issue. When I try to include child routes for the new module, an error stating that 'router-outlet' is not a known element:in lazy loaded module is thrown. In t ...