title: How to use formBuilder to create a new table row on click on button with validation and initial values
body: <p>I am trying to use formBuilder and formBuilder.array to create a new row  of user inputs (Text, Number, Drown down) to take user input and save it in Angular 7. 
  Being new to Angular 7 i am not yet able to bind the html to declared FormBuilder Array. </p>
  
  <p>I am not sure if i am doing it correct but need help on how i can do it correctly. Attaching some screenshot to make sure my issue is clear to all. </p>
  
  <p><a href="https://imgur.com/R5FMJjR" rel="nofollow noreferrer">https://imgur.com/R5FMJjR</a>
  <a href="https://i.stack.imgur.com/Y71IF.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/Y71IF.png" alt="enter image description here"></a></p>
  
  <p>Component.ts file </p>
  
  <pre><code>import { Component, OnInit } from '@angular/core';
  
  import { FormBuilder, FormGroup, Validators, FormArray } from '@angular/forms';
  
  import { CustomersService } from '../../services/customers.service';
  
  import { ContractService } from '../../services/contract.service';
  
  import {Router, ActivatedRoute} from "@angular/router"
  
  import * as _ from 'lodash';
  
  import {ContractDetailsClass} from "./contract-details-class";
  
  @Component({
    selector: 'app-contract-details',
    templateUrl: './contract-details.component.html',
    styleUrls: ['./contract-details.component.scss']
  })
  
  
  export class ContractDetailsComponent implements OnInit {
  
    customersList: Object;
    locationList: Object;
    contractTypeList: Object;
    bonusDurationList: Object;
    contract: Object;
    skillLevelsList: Object;
    ratesList: Object;
    rateType = Number;
    contractDetails:  any = [];
    contractDetailsForm: FormGroup;
    submitted = false;
  
    constructor(private formBuilder: FormBuilder, private Customers: CustomersService, private Contract: ContractService, private route: ActivatedRoute) { }
  
    ngOnInit() {
  
      var contractId = this.route.snapshot.paramMap.get("contractId");
      this.contract = {};
  
      //getContractDetails
      this.Contract.getContractDetails(contractId).subscribe( data=&gt; {
        this.contractDetails = data;
        console.log('this.contractDetails');
        if(!this.contractDetails.length){
          //If empty Add 5 rows in advance
          this.addInitialRows()
        }
      });
  
      // getContractTypes 
      this.Contract.getContractTypes().subscribe( data=&gt; {
        this.contractTypeList = data;
      });
  
      //getSkillLevels
      this.Contract.getSkillLevels().subscribe( data=&gt; {
        this.skillLevelsList = data;
      });
      //getRates
      this.Contract.getRates().subscribe( data=&gt; {
        this.ratesList = data;
      });
  
  
      // bonus 
      this.bonusDurationList = [{value: 'month', name: 'Month'}, {value: 'quarter', name: 'Quarter'}, {value: 'year', name: 'Year'} ];
  
      this.Contract.getContract(contractId).subscribe( data=&gt; {
        this.contract = data;
        var selectedContractType = _.find(this.contractTypeList, function(item){ return item.contracttypeid == data['contracttype'];})
        if(selectedContractType) this.contract['contractType'] = selectedContractType.cnttypename;
        var selectedBonusDuration = _.find(this.bonusDurationList , function(item){ return item.value == data['bonusduration'];})
        this.contract['bonusDuration'] = selectedBonusDuration.name;
      });
  
      this.contractDetailsForm =  this.formBuilder.group({
        details:this.formBuilder.array([this.addDetailsGroupToForm()])
      });
    }
  
    addDetailsGroupToForm(){
      return this.formBuilder.group({
        requirequantity: [''],
        contracttype: [''],
        skilllevel: ['', Validators.required],
        uom: [''],
        ratetype: ['', Validators.required],
        startquantity: [''],
        endquantity: [''],
        fixedcost: [''],
        margintype: [''],
        marginvalue: [''],
        billingcycle: [''],
        remark: [''],
      });
    }
  
    get details() {
      return this.contractDetailsForm.get('details') as FormArray;
    }
  
    addDetails() {
      this.details.push(this.formBuilder.control(''));
      this.details.push(this.formBuilder.control(''));
      this.details.push(this.formBuilder.control(''));
    }
  
    addInitialRows(){
      console.log("addInitialRows  called");
      this.details.push(this.formBuilder.control(''));
      this.details.push(this.formBuilder.control(''));
      this.details.push(this.formBuilder.control(''));
      this.details.push(this.formBuilder.control(''));
      this.details.push(this.formBuilder.control(''));
      console.log(this.details);
    }
  
    rateTypeChanged(){
      var values = this.contractDetailsForm.value
      console.log(values);
      this.rateType = values.rateType;
    }
  
    onSubmit(){
      var values = this.contractDetailsForm.value;
        console.log(values);
    }
  
  }
  </code></pre>
  
  <p>Component.html </p>
  
  <pre><code>&lt;div class="animated fadeIn"&gt;
      &lt;div class="row ml_margin_top_20"&gt;
        &lt;div class="col-lg-12"&gt;
          &lt;div class="card"&gt;
            &lt;form [formGroup]="contractDetailsForm" (ngSubmit)="onSubmit()"&gt;
            &lt;div class="card-header"&gt;
             &lt;span class="col-sm-8"&gt;Contract Details&lt;/span&gt; 
             &lt;span class="col-sm-4 pull-right"&gt;&lt;button aria-pressed="true" (click)="addDetails()"  class="btn btn-primary active float-right" style="position: relative;bottom: .8em;" type="button"&gt;&lt;span class="icon icon-plus"&gt;&lt;/span&gt; &lt;/button&gt;&lt;/span&gt; 
            &lt;/div&gt;
            &lt;div class="card-body"&gt;
              &lt;table formArrayName="details" *ngIf="details.length &gt; 0" class="table table-sm"&gt;
                &lt;thead&gt;
                  &lt;tr&gt;
                    &lt;th&gt;Type Of Service&lt;/th&gt;
                    &lt;th&gt;UOM&lt;/th&gt;
                    &lt;th&gt;Required Quantity&lt;/th&gt;
                    &lt;th&gt;Rate Type&lt;/th&gt;
                    &lt;th&gt;Start Quantity&lt;/th&gt;
                    &lt;th&gt;End Quantity&lt;/th&gt;
                    &lt;th&gt;Fixed Cost&lt;/th&gt;
                    &lt;th&gt;Margin Type&lt;/th&gt;
                    &lt;th&gt;Margin Value&lt;/th&gt;
                    &lt;th&gt;Billing Cycle&lt;/th&gt;
                    &lt;th&gt;Remark&lt;/th&gt;
                  &lt;/tr&gt;
                &lt;/thead&gt;
                &lt;tbody&gt;
                  &lt;tr *ngFor="let detail of details.controls ; let i = index"&gt;
                    &lt;td&gt;
                        &lt;ng-select [items]="skillLevelsList"
                        bindLabel="skilllevel"
                        placeholder="Select Skill"
                        [clearable] = false
  
                        formControlName="skilllevel"                                                                                                                                                                                                                                                                                                                                                                            
                        [ngClass]="{ 'is-invalid': submitted &amp;&amp; f.skilllevel.errors }"&gt;
                       &lt;/ng-select&gt;
                    &lt;/td&gt;
                    &lt;td &gt;
                        &lt;input type="text"  formControlName="uom"   class="form-control" id="uom" placeholder="Enter UOM"&gt;
                    &lt;/td&gt;
                    &lt;td &gt;
                        &lt;input type="number"  formControlName="requirequantity"   class="form-control" id="requirequantity" placeholder="Enter Quantity"&gt;
                    &lt;/td&gt;
                    &lt;td&gt;
                        &lt;ng-select [items]="ratesList"
                        bindLabel="ratetypename"
                        placeholder="Select Rate"
                        [clearable] = false
  
                        formControlName="ratetype"
                        [ngClass]="{ 'is-invalid': submitted &amp;&amp; f.ratetype.errors }"
                        (change)="rateTypeChanged()"&gt;
                       &lt;/ng-select&gt;
                       &lt;div *ngIf="submitted &amp;&amp; f.ratetype.errors" class="invalid-feedback"&gt;
                           &lt;div *ngIf="f.ratetype.errors.required"&gt;Rate is required&lt;/div&gt;
                       &lt;/div&gt;
                    &lt;/td&gt;
                    &lt;td &gt;
                        &lt;input type="text"  formControlName="startquantity"   class="form-control" id="uom" placeholder="Start Quantity"&gt;
                    &lt;/td&gt;
                    &lt;td &gt;
                        &lt;input type="text"  formControlName="endquantity"   class="form-control" id="uom" placeholder="End Quantity"&gt;
                    &lt;/td&gt;
                    &lt;td &gt;
                        &lt;input type="number"  formControlName="fixedcost"   class="form-control" id="fixedcost" placeholder="Enter Fixed Cost"&gt;
                    &lt;/td&gt;
                    &lt;td &gt;
                        &lt;input type="text"  formControlName="margintype"   class="form-control" id="margintype" placeholder="Enter margin type"&gt;
                    &lt;/td&gt;
                    &lt;td &gt;
                        &lt;input type="text"  formControlName="marginvalue"   class="form-control" id="marginvalue" placeholder="Enter margin value"&gt;
                    &lt;/td&gt;
                    &lt;td &gt;
                        &lt;input type="text"  formControlName="billingcycle"   class="form-control" id="billingcycle" placeholder="Enter billing cycle"&gt;
                    &lt;/td&gt;
                    &lt;td&gt;
                        &lt;input type="text"  formControlName="remark"   class="form-control" id="remark" placeholder="Enter remark"&gt;
                      &lt;/td&gt;
                    &lt;!-- &lt;td&gt;
                      &lt;span class="btn btn-primary" routerLink="/contract/edit/{{ contract.contractid}}" &gt;Edit&lt;/span&gt;
                    &lt;/td&gt; --&gt;
                  &lt;/tr&gt;
                &lt;/tbody&gt;
              &lt;/table&gt;
              &lt;div *ngIf="!details.length"&gt;
                &lt;span&gt; To add Contract Details &lt;a (click)="addDetails()" class="" &gt; Click here&lt;/a&gt;&lt;/span&gt;
              &lt;/div&gt;
              &lt;div *ngIf="details.length &gt; 0" class="row float-right ml_margin_bottom_15"&gt;
                  &lt;button  class="btn btn-primary active justify-content-center"&gt;Next&lt;/button&gt;
              &lt;/div&gt;
            &lt;/div&gt;
  
            &lt;/form&gt;
          &lt;/div&gt;
        &lt;/div&gt;
        &lt;!--/.col--&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  </code></pre>