0

I'm having a hard time integrating this form with the html. can you help me? I've tried in some ways but I couldn't connect because I'm using FormArray. I made the form but to access the controls in the html is very complicated. I need it to be form Array, because this will have several arrays with categories. I need it to be form Array, because this will have several arrays with categories.

Form in Component TS

  testeForm: FormGroup = this.fb.group({
    feedstock: this.fb.array([
      this.addFeedStockArray()
    ])
  });
  
  
    addFeedStockArray(): FormGroup {
    return this.fb.group({
      category: "",
      position: "",
      feedstockOptions: this.fb.array([
        this.addFeedStockOptions()
      ]),
   })
 }
  
  
    addFeedStockOptions(): FormGroup {
     return this.fb.group({
      name: '',
      code: '',
      price: {
        amount: '',
        currency: ['BRL'],
      }
    })
  }
  
  
  addfeedStockClick(): void {
    (<FormArray>this.testeForm.get('feedstock')).push(this.addFeedStockOptions());
  }
              <div [formGroup]="testeForm" style="margin-left: 40px">
                <div class="second-column row" formArrayName="feedstock" >
                  <div class="row" [formGroupName]="i" *ngFor="let feedstock of feedstock.get('feedstockOptions')?.controls; let i = index">
                    <div class="form-group col">
                        <label>
                          NOME:
                        </label>
                        <input class="form-control"
                              placeholder="--" formControlName="name" >
                    </div>
                    <div class="form-group col">
                        <label>
                          CÓDIGO:
                        </label>
                        <input class="form-control"
                              placeholder="--" formControlName="code">
                    </div>
                    <div class="form-group col">
                        <label>
                          PREÇO:
                        </label>
                        <input class="form-control"
                              currencyMask
                              [options]="{ prefix: 'R$ ', thousands: '.', decimal: ',', align:'left'}"
                              min="0"
                              placeholder="R$" formControlName="price" >
                    </div>
                    <div class="form-group col">
                      <i class="material-icons close-category"  style="margin-top: 40px" (click)="removefeedStockClick(i)" >
                        close
                      </i>
                    </div>
                  </div>
                </div>
              </div>

2 Answers 2

1

I would suggest a minimal change to see if it fixes your issue

<div [formGroup]="testeForm" style="margin-left: 40px">
  <div class="second-column row" formArrayName="feedstock" >
    <ng-container *ngFor="let feedstock of feedstock.get('feedstockOptions')?.controls; let i = index">
      <div class="row" [formGroupName]="i">
        <div class="form-group col">
          <label>NOME:</label>
          <input class="form-control" placeholder="--" formControlName="name" >
         </div>
      </div>
      ......
    </ng-container>

Used an ng-container to wrap the *ngFor directive

UPDATE

After seeing the complete code, realized there is one larger mistake: There are 2 levels of FormArray and need to be accessed like that.

<div [formGroup]="testeForm" style="margin-left: 40px">
  <div class="second-column row" formArrayName="feedstock" >
    <ng-container *ngFor="let fcFeedStock of testeForm.get('feedstock')?.controls; let i = index">
      <ng-container [formGroupName]="i">
        <ng-container formArrayName="feedstockOptions">
          <ng-container *ngFor="let feedstockOption of fcFeedStock.get('feedstockOptions')?.controls; let j = index">
            <div class="row" [formGroupName]="j">
              <div class="form-group col">
                <label>NOME:</label>
                <input class="form-control" placeholder="--" formControlName="name" >
              </div>
            </div>
        ......
        </ng-container>
    </ng-container>
  </ng-container>
</div>

UPDATE 2:

Showing price > amount

As price is a FormGroup, and amount is a FormControl:

 ...
 <div class="row" [formGroupName]="i">
    <div class="form-group col">
      <label>NOME:</label>
      <input class="form-control" placeholder="--" formControlName="name" >
     </div>
     <div formGroupName="price">
       <input formControlName="amount">
     </div>
  </div>
  ...

How to add one new element to the array:

The issue is you are confusing between the 2 FormArrays 'feedstock' and 'feedstockOptions'.

// This function should do feedstock.push(this.addFeedStockArray())
addfeedStockClick(): void {
  (<FormArray>this.testForm.get('feedstock')).push(this.addFeedStockArray());
}

For adding to feedstockOptions, you first need the index of the feedstock, access it's feedstockOptions, and then push to it:

(<FormArray>(<FormArray>this.testForm.get('feedstock')).at(index).get('feedstockOptions')).push(this.addFeedStockOptions());

or if you can manage to directly access the fcFeedstock, the line of code would simplify to:

(<FormArray>fcFeedstock.get('feedstockOptions')).push(this.addFeedStockOptions())
Sign up to request clarification or add additional context in comments.

3 Comments

Hi, I made some tweaks to fit my code and it worked perfectly. Thank you very much. Two more questions, how do I access amount? in price: { amount: "", currency: '' } Last doubt, I'm trying to add a new array like this, addfeedStockClick(): void { (<FormArray>this.testForm.get('feedstock')).push(this.addFeedStockOptions()); } however it is taking the values from the old array.
In HTML /// <div class="divide-section"> <div class="first-column" [formGroup]="testeForm"><div class="header-section options" (click)="addfeedStockClick()"><span>ADD </span> <i class="material-icons"> add </i> </div> </div> <div [formGroup]="testeForm" style="margin-left: 40px"> <div class="second-column row" formArrayName="feedstock" > <ng-container *ngFor="let fcFeedStock of testeForm.get('feedstock')?.controls; let i = index"><ng-container [formGroupName]="i"><div class="form-group"> ///
I have updated the answer with explanation to suit your scenario.
0

First you need to declare the form group with a form array in it

public uploadformGroup = this._fb.group({ products: new FormArray([], [Validators.required], []), });

get the specific array from the form group as form array

get arrayformControls() { return (this.uploadformGroup.get('products') as FormArray).controls; };

then run in a loop and insert each form group to the form array

this._api.getProducts().subscribe({
  next: (res) => {
    this.results = res;
    this.results.forEach((ob,i) => {
      this.arrayformControls.push(
          new FormGroup({
          productName: new FormControl(ob.productName, [Validators.required, Validators.minLength(5)]),
        })
      );
    });
    console.log('this.arrayformControls',this.arrayformControls);
    console.log('this.arrayformControls',this.uploadformGroup);


  },
  error: (err) => {},
  complete: () => {
    this.uploadformGroup.value.products = this.arrayformControls
  },
});

html will look like that

<form
  [formGroup]="profileFormArray"
  (ngSubmit)="checkArrayOfProductsInForm($event)"
>
  <div formArrayName="productsForm">
    <button type="submit" [disabled]="!productsForm.valid">
      Submit changes and assign from form to products array
    </button>
    <div *ngFor="let p of productsForm.controls; let i = index">
      <!-- The repeated alias template -->
      <div>Id:{{ this.products[i].id }}</div>
      <div>Name:{{ this.products[i].productName }}</div>
      <input
        type="text"
        [formControlName]="i"
        (keyup)="changeIndexOfProduct(i)"
      />
    </div>
  </div>
</form>

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.