Angular Reactive Forms with nested Form Arrays

前端 未结 3 1393
执念已碎
执念已碎 2020-11-28 21:01

I\'m new to Angular 2 and decided the best way to learn would be to go through the official Angular guides.

I went through the Reactive Forms Guide https://angular.i

相关标签:
3条回答
  • 2020-11-28 21:14

    It's not very much different to have a nested formarray. Basically you just duplicate the code you have... with nested array :) So here's a sample:

    myForm: FormGroup;
    
    constructor(private fb: FormBuilder) {
      this.myForm = this.fb.group({
        // you can also set initial formgroup inside if you like
        companies: this.fb.array([])
      })
    }
    
    addNewCompany() {
      let control = <FormArray>this.myForm.controls.companies;
      control.push(
        this.fb.group({
          company: [''],
          // nested form array, you could also add a form group initially
          projects: this.fb.array([])
        })
      )
    }
    
    deleteCompany(index) {
      let control = <FormArray>this.myForm.controls.companies;
      control.removeAt(index)
    }
    

    So that is the add and delete for the outermost form array, so adding and removing formgroups to the nested form array is just duplicating the code. Where from the template we pass the current formgroup to which array you want to add (in this case) a new project/delete a project.

    addNewProject(control) {
      control.push(
        this.fb.group({
          projectName: ['']
      }))
    }
    
    deleteProject(control, index) {
      control.removeAt(index)
    }
    

    And the template in the same manner, you iterate your outer formarray, and then inside that iterate your inner form array:

    <form [formGroup]="myForm">
      <div formArrayName="companies">
        <div *ngFor="let comp of myForm.get('companies').controls; let i=index">
        <h3>COMPANY {{i+1}}: </h3>
        <div [formGroupName]="i">
          <input formControlName="company" />
          <button (click)="deleteCompany(i)">
             Delete Company
          </button>
          <div formArrayName="projects">
            <div *ngFor="let project of comp.get('projects').controls; let j=index">
              <h4>PROJECT {{j+1}}</h4>
              <div [formGroupName]="j">
                <input formControlName="projectName" />
                <button (click)="deleteProject(comp.controls.projects, j)">
                  Delete Project
                </button>
              </div>
            </div>
            <button (click)="addNewProject(comp.controls.projects)">
              Add new Project
            </button>
          </div>
        </div>
      </div>
    </div>
    

    DEMO

    EDIT:

    To set values to your form once you have data, you can call the following methods that will iterate your data and set the values to your form. In this case data looks like:

    data = {
      companies: [
        {
          company: "example comany",
          projects: [
            {
              projectName: "example project",
            }
          ]
        }
      ]
    }
    

    We call setCompanies to set values to our form:

    setCompanies() {
      let control = <FormArray>this.myForm.controls.companies;
      this.data.companies.forEach(x => {
        control.push(this.fb.group({ 
          company: x.company, 
          projects: this.setProjects(x) }))
      })
    }
    
    setProjects(x) {
      let arr = new FormArray([])
      x.projects.forEach(y => {
        arr.push(this.fb.group({ 
          projectName: y.projectName 
        }))
      })
      return arr;
    }
    
    0 讨论(0)
  • 2020-11-28 21:16

    Here is what I did I used angularflexlayout and angular material, you can yous any library, just wanted to show you the functionality

         <form [formGroup]="editForm" novalidate fxLayout="column"
            autocomplete="off">
    
        <div fxLayout="row wrap" fxLayoutGap="2em">
          <mat-form-field [fxFlex]="30">
            <mat-label>Name</mat-label>
            <input matInput formControlName="name" width="800px"/>
          </mat-form-field>
    
        </div>
        <div fxLayout="column" fxLayoutGap="3em">
          <div fxLayout="row wrap" fxFlex="40" fxLayoutGap="2em">
            <div formArrayName="phones" fxFlex="50" fxLayoutGap="8px" *ngFor="let phone of Phones.controls;let i= index">
              <mat-form-field fxFlex="100" [formGroupName]="i">
                <mat-label>Phone</mat-label>
                <input matInput formControlName="phone"/>
              </mat-form-field>
            </div>
            <button type="button" mat-stroked-button color="primary" (click)="addPhone()">add</button>
          </div>
          <div fxLayout="row wrap" fxFlex="40" fxLayoutGap="2em">
            <div formArrayName="emails" fxFlex="50" fxLayoutGap="8px" *ngFor="let email of Emails.controls;let i= index">
              <mat-form-field fxFlex="100" [formGroupName]="i">
                <mat-label>Email</mat-label>
                <input matInput formControlName="email"/>
              </mat-form-field>
            </div>
            <button type="button" mat-stroked-button color="primary" (click)="addEmail()">add</button>
          </div>
        </div>
    
        <div class="mr-2" fxLayoutAlign="end" mat-dialog-actions>
          <button type="button" (click)="cancelDialog()" mat-button
                  mat-dialog-close>Cancel
          </button>
    
          <button type="button" (click)="onSubmit()"
                  mat-raised-button
                  color="primary">
            Submit
          </button>
        </div>
    
      </form>
    

    then angular controller

      editForm: FormGroup;
      phones: FormArray;
      emails: FormArray;
    
      createForm() {
        this.editForm = this.fb.group({
          name: [''],
            phones: this.fb.array([this.createPhone()]),
          emails: this.fb.array([this.createEmail()]),
         });
    
      }
    
      get Phones() {
        return this.editForm.get('phones') as FormArray;
      }
    
      get Emails() {
        return this.editForm.get('emails') as FormArray;
      }
    
     createPhone() {
        return this.fb.group(({
          phone: '',
        }));
      }
    
      createEmail() {
        return this.fb.group(({
          email: ''
        }));
      }
    
    
      addPhone(): void {
        this.phones = this.editListingForm.get('phones') as FormArray;
        this.phones.push(this.createPhone());
      }
    
      addEmail(): void {
        this.emails = this.editListingForm.get('emails') as FormArray;
        this.emails.push(this.createEmail());
      }
    
    0 讨论(0)
  • 2020-11-28 21:23

                        <tr formArrayName="entries"
                            *ngFor="let field of entriesGroup.get('entries').controls; let ind1 = index;">
                            <td [formGroupName]="ind1">
                                <input type="text" disabled formControlName="date1" name="date1"
                                    class="form-control">
                            </td>
    
    
                            <td [formGroupName]="ind1" *ngIf="hideHeaders">
                                <div formGroupName="odometerReadingDetails">
                                    <input type="text" formControlName="startingLocation" name="startingLocation"
                                        class="form-control">
                                </div>
                            </td>
                            <td [formGroupName]="ind1" *ngIf="hideHeaders">
                                <div formGroupName="odometerReadingDetails">
                                    <input type="text" formControlName="endingLocation" name="endingLocation"
                                        class="form-control">
                                </div>
                            </td>
    
    
                            <td [formGroupName]="ind1" *ngIf="hideHeaders">
                                <div formGroupName="odometerReadingDetails">
                                    <input type="text" formControlName="odometerReadStartingPoint"
                                        name="odometerReadStartingPoint" class="form-control"
                                        [ngModel]="ind1!=0?entriesGroup.get('entries').controls[ind1-1].get('odometerReadingDetails').get('odometerReadEndingPoint').value:field.get('odometerReadingDetails').get('odometerReadStartingPoint').value">
                                </div>
                            </td>
                            <td [formGroupName]="ind1" *ngIf="hideHeaders">
                                <div formGroupName="odometerReadingDetails">
                                    <input type="text" formControlName="odometerReadEndingPoint"
                                        name="odometerReadEndingPoint" class="form-control"
                                        [ngModel]="ind1<entriesGroup.get('entries').controls.length-1?entriesGroup.get('entries').controls[ind1+1].get('odometerReadingDetails').get('odometerReadStartingPoint').value:field.get('odometerReadingDetails').get('odometerReadEndingPoint').value">
                                </div>
                            </td>
                            <td [formGroupName]="ind1" *ngIf="hideHeaders">
                                <div formGroupName="odometerReadingDetails">
                                    <input type="text" disabled formControlName="odometerReadForOfficial"
                                        name="odometerReadForOfficial" class="form-control"
                                        [ngModel]="field.get('odometerReadingDetails').get('totalKilometersCovered').value-field.get('odometerReadingDetails').get('odometerReadForPersonal').value">
                                </div>
                            </td>
                            <td [formGroupName]="ind1" *ngIf="hideHeaders">
                                <div formGroupName="odometerReadingDetails">
                                    <input type="text" formControlName="odometerReadForPersonal"
                                        name="odometerReadForPersonal" class="form-control">
                                </div>
                            </td>
                            <td [formGroupName]="ind1" *ngIf="hideHeaders">
                                <div formGroupName="odometerReadingDetails">
                                    <input type="text" disabled formControlName="totalKilometersCovered"
                                        name="totalKilometersCovered" class="form-control"
                                        [ngModel]="field.get('odometerReadingDetails').get('odometerReadEndingPoint').value!=0?field.get('odometerReadingDetails').get('odometerReadEndingPoint').value-field.get('odometerReadingDetails').get('odometerReadStartingPoint').value:0">
                                </div>
                            </td>
                            <td [formGroupName]="ind1" *ngIf="hideHeaders">
                                <div formGroupName="odometerReadingDetails">
                                    <textarea rows="2" cols="20" type="text" formControlName="particularTravel"
                                        name="particularTravel" class="form-control">
    
                             </textarea>
                                </div>
                            </td>
    
    
    
                            <td [formGroupName]="ind1" *ngIf="fuelHide">
                                <div formGroupName="fuelDetails">
                                    <input type="text" formControlName="fuelFilled" name="fuelFilled"
                                        class="form-control">
                                </div>
                            </td>
                            <td [formGroupName]="ind1" *ngIf="fuelHide">
                                <div formGroupName="fuelDetails">
                                    <input type="text" formControlName="costPerLiter" name="costPerLiter"
                                        class="form-control">
                                </div>
                            </td>
                            <td [formGroupName]="ind1" *ngIf="fuelHide">
                                <div formGroupName="fuelDetails">
                                    <input type="text" disabled formControlName="costOfTheFuel" name="costOfTheFuel"
                                        class="form-control"
                                        [ngModel]="field.get('fuelDetails').get('costPerLiter').value * field.get('fuelDetails').get('fuelFilled').value">
                                </div>
                            </td>
    
                            <td [formGroupName]="ind1" *ngIf="fuelHide">
                                <div formGroupName="fuelDetails">
                                    <input type="text" disabled formControlName="fuelConsumption"
                                        name="fuelConsumption" class="form-control"
                                        [ngModel]="field.get('fuelDetails').get('costOfTheFuel').value!=0?(ind1!=0?(entriesGroup.get('entries').controls[ind1-1].get('fuelDetails').get('fuelConsumption').value + field.get('fuelDetails').get('costOfTheFuel').value):field.get('fuelDetails').get('costOfTheFuel').value):0">
                                </div>
                            </td>
                            <td [formGroupName]="ind1" *ngIf="NoNeed">
                                <div formGroupName="fuelDetails">
                                    <input type="text" formControlName="requestId" name="requestId"
                                        class="form-control">
                                </div>
                            </td>
                            <td [formGroupName]="ind1" *ngIf="fuelHide">
                                <div formGroupName="fuelDetails">
                                    <input type="text" formControlName="couponCode" name="couponCode"
                                        class="form-control">
                                </div>
                            </td>
                            <td [formGroupName]="ind1" *ngIf="hideDate">
                                <div formGroupName="fuelDetails">
                                    <input type="text" formControlName="couponDate" name="couponDate"
                                        placeholder="date1,date2,..." class="form-control">
                                </div>
                            </td>
    
                            <td [formGroupName]="ind1" *ngIf="fuelHide">
                                <div formGroupName="fuelDetails">
                                    <input type="text" formControlName="couponNumber" name="couponNumber"
                                        placeholder="coupon1,coupon2,..." class="form-control">
                                </div>
                            </td>
    
                            <td [formGroupName]="ind1" *ngIf="hideDate">
                                <div formGroupName="fuelDetails">
                                    <input type="text" formControlName="couponsAmount" name="couponsAmount"
                                        class="form-control">
                                </div>
                            </td>
    
                            <td [formGroupName]="ind1" *ngIf="repaireHide">
                                <div formGroupName="vehicleRepairDetails">
                                    <input type="text" formControlName="totalKmsCoveredBeforeRepair"
                                        name="totalKmsCoveredBeforeRepair" class="form-control" readonly
                                        [ngModel]="field.get('odometerReadingDetails').get('totalKilometersCovered').value">
                                </div>
                            </td>
    
                            <td [formGroupName]="ind1" *ngIf="repaireHide">
                                <div formGroupName="vehicleRepairDetails">
                                    <input type="text" formControlName="sparesCost" name="sparesCost"
                                        class="form-control">
                                </div>
                            </td>
    
                            <td [formGroupName]="ind1" *ngIf="repaireHide">
                                <div formGroupName="vehicleRepairDetails">
                                    <input type="text" formControlName="labourCost" name="labourCost"
                                        class="form-control">
                                </div>
                            </td>
    
    
                            <td [formGroupName]="ind1" *ngIf="repaireHide">
                                <div formGroupName="vehicleRepairDetails">
                                    <input type="text" formControlName="vehicleRepaireCost"
                                        name="vehicleRepaireCost" class="form-control"
                                        [ngModel]="field.get('vehicleRepairDetails').get('sparesCost').value*1 + field.get('vehicleRepairDetails').get('labourCost').value*1">
                                </div>
                            </td>
                            <td [formGroupName]="ind1" *ngIf="repaireHide">
                                <div formGroupName="vehicleRepairDetails">
    
                                    <textarea rows="2" cols="20" type="text" formControlName="particularsOfRepairs"
                                        name="particularsOfRepairs" class="form-control">
    
                               </textarea>
                                </div>
                            </td>
                            <td [formGroupName]="ind1" *ngIf="workShop">
                                <div formGroupName="vehicleRepairDetails">
                                    <select formControlName="workshopId" class="form-control"
                                        (click)="workshopDetails1($event,ind1)">
    
                                        <option *ngFor="let i of workshopdata"
                                            [selected]="i.workShopId==field.get('vehicleRepairDetails').get('workshopId').value">
                                            {{i.workShopId}}</option>
                                        <option value="others">OTHERS</option>
                                    </select>
                                </div>
                            </td>
    
    
                            <td [formGroupName]="ind1" *ngIf="workShop">
                                <div formGroupName="vehicleRepairDetails">
                                    <textarea rows="2" cols="50" type="text" formControlName="workshopAddress"
                                        name="workshopAddress" class="form-control">
               </textarea>
                                </div>
                            </td>
    
                            <td [formGroupName]="ind1" *ngIf="workShop">
                                <div formGroupName="vehicleRepairDetails">
                                    <input type="text" formControlName="workshopContactNumber"
                                        name="workshopContactNumber" class="form-control">
                                </div>
                            </td>
    
                            <td [formGroupName]="ind1" *ngIf="workShop">
                                <div formGroupName="vehicleRepairDetails">
    
                                    <textarea rows="2" cols="50" type="text"
                                        formControlName="workshopAccountDetails" name="workshopAccountDetails"
                                        class="form-control">
               </textarea>
                                </div>
                            </td>
                            <td [formGroupName]="ind1" *ngIf="repaireHide">
                                <div formGroupName="vehicleRepairDetails">
                                    <input type="text" formControlName="requestId" name="requestId"
                                        class="form-control">
                                </div>
                            </td>
    
    
    
    
                            <td [formGroupName]="ind1" *ngIf="driverHide">
                                <div formGroupName="driverChargesDetails">
                                    <select formControlName="categoryType" class="form-control"
                                        (click)="onCatType1($event,ind1)">
                                        <option>Choose</option>
                                        <option *ngFor="let i of driverChargesLimit"
                                            [selected]="i.categoryType==field.get('driverChargesDetails').get('categoryType').value">
                                            {{i.categoryType}}</option>
    
                                    </select>
                                </div>
                            </td>
    
                            <td [formGroupName]="ind1" *ngIf="driverHide">
                                <div formGroupName="driverChargesDetails">
                                    <input type="text" formControlName="amount" name="amount" class="form-control"
                                        disabled>
                                </div>
                            </td>
    
                            <td [formGroupName]="ind1" *ngIf="driverHide">
                                <div formGroupName="driverChargesDetails">
                                    <input type="time" formControlName="startingTime" name="startingTime"
                                        class="form-control" (change)="onStartTime1($event,ind1)">
                                </div>
                            </td>
    
                            <td [formGroupName]="ind1" *ngIf="driverHide">
                                <div formGroupName="driverChargesDetails">
                                    <input type="time" formControlName="endingTime"
                                        (change)="onEndTime1($event,ind1)" name="endingTime" class="form-control">
                                </div>
                            </td>
    
                        </tr>
    
                    </tbody>
                </div>
            </table>
    
    0 讨论(0)
提交回复
热议问题