Angular 2 Dynamic Nested Form

后端 未结 1 792
梦毁少年i
梦毁少年i 2021-02-07 14:36

Basically I want to create a dynamic form with nested objects like the picture below:

  • Pay offs are in an array on the model
  • We should be able to add/remo
相关标签:
1条回答
  • 2021-02-07 15:20

    I had to figure this out on my own because it seems that forms are still changing in Angular 2 and I've not seen any other examples similar to this (although it seems like a very common use-case).

    Here is a plunkr of working example using Angular2 RC3.

    I am using updated Angular 2 form code from this document.

    app.component.ts (contains the form):

    import { Component } from '@angular/core';
    import {REACTIVE_FORM_DIRECTIVES, FormControl, FormGroup, FormArray} from '@angular/forms';
    
    @Component({
      selector: 'my-app',
      templateUrl: 'app/app.html',
      directives: [REACTIVE_FORM_DIRECTIVES],
      providers:  []
    })
    export class AppComponent {
      form: FormGroup;
      myModel:any;
    
      constructor() {
        // initializing a model for the form to keep in sync with. 
        // usually you'd grab this from a backend API
        this.myModel = {
          name: "Joanna Jedrzejczyk",
          payOffs: [
            {amount: 111.11, date: "Jan 1, 2016", final: false},
            {amount: 222.22, date: "Jan 2, 2016", final: true}
            ]
        }
    
        // initialize form with empty FormArray for payOffs
        this.form = new FormGroup({
          name: new FormControl(''),
          payOffs: new FormArray([])
        });
    
        // now we manually use the model and push a FormGroup into the form's FormArray for each PayOff
        this.myModel.payOffs.forEach( 
          (po) => 
            this.form.controls.payOffs.push(this.createPayOffFormGroup(po))
        );
      }
    
      createPayOffFormGroup(payOffObj) {
        console.log("payOffObj", payOffObj);
        return new FormGroup({
          amount: new FormControl(payOffObj.amount),
          date: new FormControl(payOffObj.date),
          final: new FormControl(payOffObj.final)
        });
      }
    
      addPayOff(event) {
        event.preventDefault(); // ensure this button doesn't try to submit the form
        var emptyPayOff = {amount: null, date: null, final: false};
    
        // add pay off to both the model and to form controls because I don't think Angular has any way to do this automagically yet
        this.myModel.payOffs.push(emptyPayOff);
        this.form.controls.payOffs.push(this.createPayOffFormGroup(emptyPayOff));
        console.log("Added New Pay Off", this.form.controls.payOffs)
      }
    
      deletePayOff(index:number) {
        // delete payoff from both the model and the FormArray
        this.myModel.payOffs.splice(index, 1);
        this.form.controls.payOffs.removeAt(index);
      }
    }
    

    Notice above that I manually push new FormGroup objects into the form.controls.payOffs array, which is a FormArray object.

    app.html (contains form html):

      <form (ngSubmit)="onSubmit()" [formGroup]="form">
    
        <label>Name</label>
        <input type="text" formControlName="name" [(ngModel)]="myModel.name" placeholder="Name">
    
        <p>Pay Offs</p>
        <table class="simple-table">
          <tr>
            <th>Amount</th>
            <th>Date</th>
            <th>Final?</th>
            <th></th>
          </tr>
        <tbody>
          <tr *ngFor="let po of form.find('payOffs').controls; let i = index">
            <td>
              <input type="text" size=10 [formControl]="po.controls.amount" [(ngModel)]="myModel.payOffs[i].amount">
            </td>
            <td>
              <input type="text" [formControl]="po.controls.date" [(ngModel)]="myModel.payOffs[i].date">
            </td>
            <td>
              <input type="checkbox" [formControl]="po.controls.final" [(ngModel)]="myModel.payOffs[i].final">
            </td>
            <td>
              <button (click)="deletePayOff(i)" style="color: white; background: rgba(255, 0, 0, .5)">x</button>
            </td>
          </tr>
        </tbody>
        <tr>
          <td colspan="4" style="text-align: center; padding: .5em;">
            <button (click)="addPayOff($event)" style="color: white; background: rgba(0, 150, 0, 1)">Add Pay Off</button>
          </td>
        </tr>
        </table>
    
      </form>
    

    In the html form I link the form to the model on the inputs with statements like so:

    ... [formControl]="po.controls.amount" [(ngModel)]="myModel.payOffs[i].amount" ...
    
    0 讨论(0)
提交回复
热议问题