5

I want to add row dynamically when I click the button. I'm using reactive-form for this. Here's what I'm talking about

here is my html code

<table>
    <thead>
        <tr class='tableHeader'>
            <div fxLayout="row" fxLayoutAlign="start center" fxFlex="1 0 auto">
                <td fxFlex="22" class="pr-4">Name</td>
                <td fxFlex="15" class="pr-4">Price</td>
                <td fxFlex="15" class="pr-4">Loan Term</td>
                <td fxFlex="15" class="pr-4">Quantity</td>
                <td fxFlex="15" class="pr-4">Deposit</td>
                <td fxFlex="15" class="pr-4">Total</td>
            </div>
        </tr>
    </thead>
    <tbody>
        <tr [formGroup]="loanProductForm">
            <div fxLayout="row" fxLayoutAlign="start center" fxFlex="1 0 auto">
                <td fxFlex="22">
                    <mat-form-field appearance="outline" fxFlex="100" class="pr-4">
                        <mat-label>Product </mat-label>
                        <mat-select formControlName="productId" required>
                            <mat-option *ngFor="let product of productList" [value]="product.productId">
                                {{product.name}}
                            </mat-option>
                        </mat-select>
                    </mat-form-field>
                </td>
                <td fxFlex="15">
                    <mat-form-field appearance="outline" fxFlex="100" class="pr-4">
                        <mat-label>Price </mat-label>
                        <input type='number' matInput formControlName="price" name="" id="" placeholder="Price" required>
                    </mat-form-field>
                </td>
                <td fxFlex="15">
                    <mat-form-field appearance="outline" fxFlex="100" class="pr-4">
                        <mat-label>Loan Term </mat-label>
                        <mat-select formControlName="loanTermId" required>
                            <mat-option *ngFor="let loanTerm of loanTermList" [value]="loanTerm.loanTermId">
                                {{loanTerm.numberOfMonths}}
                            </mat-option>
                        </mat-select>
                    </mat-form-field>
                </td>
                <td fxFlex="15">
                    <mat-form-field appearance="outline" fxFlex="100" class="pr-4">
                        <mat-label>Quantity </mat-label>
                        <input type='number' formControlName="quantity" matInput name="" id="" placeholder="Quantity" required>
                    </mat-form-field>
                </td>
                <td fxFlex="15">
                    <mat-form-field appearance="outline" fxFlex="100" class="pr-4">
                        <mat-label>Deposit </mat-label>
                        <input type='number' formControlName="deposit" matInput name="" id="" placeholder="Deposit" required>
                    </mat-form-field>
                </td>
                <td fxFlex="15">
                    <mat-form-field appearance="outline" fxFlex="100" class="pr-4">
                        <mat-label>Total </mat-label>
                        <input type='number' formControlName="total" matInput name="" id="" placeholder="Total" required>
                    </mat-form-field>
                </td>

            </div>
        </tr>
        <tr>
            <td fxFlex="10">
                <div fxLayout="row" fxLayoutAlign="start center" fxFlex="1 0 auto">
                    <button mat-stroked-button class='addBtn btn-style-2' fxFlex='100' (click)='addTableRow()'>Add
                        <mat-icon matSuffix>add_box</mat-icon>
                    </button>
                </div>
            </td>
        </tr>
    </tbody>
</table>

and here is how I'm trying in my ts file

   this.loanProductForm = this._formBuilder.group({
      productId: ['', Validators.required],
      price: ['', Validators.required],
      loanTermId: ['', Validators.required],
      quantity: ['', Validators.required],
      deposit: ['', Validators.required],
      total: ['', Validators.required],
    })


addTableRow() {
    this.newRow = { productId: '', price: '', loanTermId: '', quantity: '', deposit: '', total: '' };
    // this.tableRows.push(this.newRow)
  }

but the code won't let me use push method on this form

6
  • I guess you mean reactive-form ? Commented Nov 20, 2019 at 11:21
  • yes exactly, sorry I typo, I'm just correcting it Commented Nov 20, 2019 at 11:22
  • Add another line of form or add the form value as a line? Commented Nov 20, 2019 at 11:25
  • I mean the add button will insert a new row below Commented Nov 20, 2019 at 11:26
  • new row of values or a new row of inputs? Commented Nov 20, 2019 at 11:27

3 Answers 3

6

You need to use Form Array in this case.

Try like this:

Working Demo

.ts

this.loanProductForm = this.fb.group({
  products: this.fb.array([
    this.addProductFormGroup()
  ])
});

 addProductFormGroup(): FormGroup {
    return this.fb.group({
      productId: ['', Validators.required],
      price: ['', Validators.required],
      loanTermId: ['', Validators.required],
      quantity: ['', Validators.required],
      deposit: ['', Validators.required],
      total: ['', Validators.required],
    });
  }

addProductButtonClick(): void {
   (<FormArray>this.loanProductForm.get('products')).push(this.addProductFormGroup());
}

.html

 <button type="button" (click)="addProductButtonClick()">
          Add Product
 </button>
Sign up to request clarification or add additional context in comments.

17 Comments

I'm getting error on your second code snippet. Cannot find name addProductFormGroup where should I write this code. I wrote it just just under the the formBuilder group as in your
It is a separate function
Sorry, my code complied and executed successfully but its not working, i.e. not adding row on click event. Nor do it is producing any error on console
Check the demo I shared
its working now, but there's a little trouble and that as as I click the add button, the new row instantly becomes red (like that in case of form invalid) to avoid that problem
|
3

I think this should help you:

https://alligator.io/angular/reactive-forms-formarray-dynamic-fields/

2 Comments

this link is broken
Sorry. Repaired
1

You need to use form array instead of form group :

ts

  ...

       this.loanProductForm = this._formBuilder.group(
           loanProductArray : this._formBuilder.array([this.buildGroup()])
    ) ;


    get loanProductArray(){
      return this.loanProductForm.get('loanProductArray ') as FormArray ;
    }

    buildGroup(){
    return    this.loanProductForm = this._formBuilder.group({
          productId: ['', Validators.required],
          price: ['', Validators.required],
          loanTermId: ['', Validators.required],
          quantity: ['', Validators.required],
          deposit: ['', Validators.required],
          total: ['', Validators.required],
        })
    }

addTableRow() {
   this.loanProductArray.push(this.buildGroup()) ;
  }

html

    ...

 <tbody [formGroup]="loanProductForm">
   <ng-container formArrayName="loanProductArray">
        <tr *ngFor="let line of loanProductArray.controls; let i=index" [formGroupName]="i">
            <div fxLayout="row" fxLayoutAlign="start center" fxFlex="1 0 auto">
                <td fxFlex="22">
                    <mat-form-field appearance="outline" fxFlex="100" class="pr-4">
                        <mat-label>Product </mat-label>
                        <mat-select formControlName="productId" required>
                            <mat-option *ngFor="let product of productList" [value]="product.productId">
                                {{product.name}}
                            </mat-option>
                        </mat-select>
                    </mat-form-field>
                </td>
                <td fxFlex="15">
                    <mat-form-field appearance="outline" fxFlex="100" class="pr-4">
                        <mat-label>Price </mat-label>
                        <input type='number' matInput formControlName="price" name="" id="" placeholder="Price" required>
                    </mat-form-field>
                </td>
                <td fxFlex="15">
                    <mat-form-field appearance="outline" fxFlex="100" class="pr-4">
                        <mat-label>Loan Term </mat-label>
                        <mat-select formControlName="loanTermId" required>
                            <mat-option *ngFor="let loanTerm of loanTermList" [value]="loanTerm.loanTermId">
                                {{loanTerm.numberOfMonths}}
                            </mat-option>
                        </mat-select>
                    </mat-form-field>
                </td>
                <td fxFlex="15">
                    <mat-form-field appearance="outline" fxFlex="100" class="pr-4">
                        <mat-label>Quantity </mat-label>
                        <input type='number' formControlName="quantity" matInput name="" id="" placeholder="Quantity" required>
                    </mat-form-field>
                </td>
                <td fxFlex="15">
                    <mat-form-field appearance="outline" fxFlex="100" class="pr-4">
                        <mat-label>Deposit </mat-label>
                        <input type='number' formControlName="deposit" matInput name="" id="" placeholder="Deposit" required>
                    </mat-form-field>
                </td>
                <td fxFlex="15">
                    <mat-form-field appearance="outline" fxFlex="100" class="pr-4">
                        <mat-label>Total </mat-label>
                        <input type='number' formControlName="total" matInput name="" id="" placeholder="Total" required>
                    </mat-form-field>
                </td>

            </div>
        </tr>
        <tr>
            <td fxFlex="10">
                <div fxLayout="row" fxLayoutAlign="start center" fxFlex="1 0 auto">
                    <button mat-stroked-button class='addBtn btn-style-2' fxFlex='100' (click)='addTableRow()'>Add
                        <mat-icon matSuffix>add_box</mat-icon>
                    </button>
                </div>
            </td>
        </tr>
</<ng-container>
    </tbody>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.