1

I want to add a row when I click on Add button, the table exists in a Reactive form.

Here's the structure that I'm talking about

Here's how I tried html file

<tr *ngFor='let row of tableRows'>
    <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 [(ngModel)]="tableRows.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 [(ngModel)]="tableRows.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 [(ngModel)]="tableRows.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' matInput [(ngModel)]="tableRows.quantity" 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' matInput [(ngModel)]="tableRows.deposit" 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' matInput [(ngModel)]="tableRows.total" name="" id="" placeholder="Total" required>
            </mat-form-field>
        </td>

and here's how I'm trying in ts file

newRow = { productId: '', price: '', loanTermId: '', quantity: '', deposit: '', total: '' };
tableRows = [{ productId: '', price: '', loanTermId: '', quantity: '', deposit: '', total: '' }];

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

Hoping that I'd work. I receive the following error in console

ERROR Error: 
      ngModel cannot be used to register form controls with a parent formGroup directive.  Try using
      formGroup's partner directive "formControlName" instead.
3
  • 2
    if you use reactive forms you can use formarray. angular.io/guide/… Commented Nov 19, 2019 at 18:23
  • thanks, but how do I achieve the functionality of adding a row on click event ? Commented Nov 19, 2019 at 18:25
  • Angular is creating a FormGroup instance for you since you are probably using the form element somewhere in your template, and using ngModel directive defeats the purpose of the FormGroup system. If what you want is to get rid of the error without changing your implementation, try adding ngNoForm to your form element, as in <form ngNoForm> ..., but I strongly recommend you to have a look at angular's formGroup, formArray and formControls, they really help in these cases. Commented Nov 19, 2019 at 19:42

1 Answer 1

3

You cannot use ngModel with FormControl. Instead Use FormControlName and FormArray. In component,ts file

 import { FormBuilder, FormGroup, FormArray, FormControl } from '@angular/forms';

In constructor:: constructor(private fb: FormBuilder) { }

    ngOnInit() {

    /* Initiate the form structure */
    this.productForm = this.fb.group({
      pData: this._fb.array([])
    })
    this.addFormDetails();
  }

   addFormDetails {
     this.rowDataArray.push(this.BuildFormDynamic(data_from_backend));
   }

    get formData() { // use getter method to get the row array
       return this.productForm.get('pData') as FormArray;
  }

Access data_from_backend and assign it here, if black then no data will show in HTML, if have value then values will be displayed on HTML

    BuildFormDynamic(data_from_backend): FormGroup {
    return this._fb.group({
      abc: [data_from_backend.abc],
      def: [data_from_backend.def],
      ghi: [data_from_backend.ghi],
      jkl: [data_from_backend.jkl],
      mno: [data_from_backend.mno],
      pqr: [data_from_backend.pqr]
    });
  }

In HTML, access these valiable using FOrmControlName Name your form elementproductForm: FormGroup; Same form name should be given in html file like this::

    `<form [formGroup]="productForm">
      <div formArrayName="pData">
    <div *ngFor="let item of formData.controls; let pointIndex=index" [formGroupName]="pointIndex">
    <label>
      Test Name: <input formControlName="abc" />
    </label>
<button type="button" (click)="deleteFormRows(pointIndex)">Delete Selling Point</button>
    </div>
<button type="button" (click)="addFormRows()">Add Selling Point</button>
  </div>
    </form>`

To add and Delete rows

 addFormRows() {
    this.formData.push(this.fb.group({point:''}));
  }
deleteFormRows(index) {
    this.formData.removeAt(index);
  }

This is just an example, customise it according to your requirement. Lemme know if any issues

Sign up to request clarification or add additional context in comments.

2 Comments

I read the angular guide of reactive forms with the similar example as of mine, but the problem is that in guide they were only using a single input, where as I've a complete table. that's why I'm stuck
I have made some edit to add as many as data is required in formControlArray

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.